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 GtkWindowClass *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);
1084 /* Set window icon */
1085 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1087 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1088 g_object_unref (window_icon);
1093 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1095 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1097 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1098 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1099 priv->clipboard_change_handler_id))
1100 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1101 priv->clipboard_change_handler_id);
1102 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1103 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1104 priv->default_clipboard_change_handler_id))
1105 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1106 priv->default_clipboard_change_handler_id);
1108 if (priv->account_removed_handler_id &&
1109 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1110 priv->account_removed_handler_id))
1111 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1112 priv->account_removed_handler_id);
1116 modest_msg_edit_window_finalize (GObject *obj)
1118 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1120 g_object_unref (priv->custom_header_pairs);
1122 if (priv->max_chars_banner) {
1123 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1124 priv->max_chars_banner = FALSE;
1127 /* Sanity check: shouldn't be needed, the window mgr should
1128 call this function before */
1129 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1131 if (priv->font_dialog != NULL) {
1132 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1135 if (priv->clipboard_text != NULL) {
1136 g_free (priv->clipboard_text);
1137 priv->clipboard_text = NULL;
1140 if (priv->draft_msg != NULL) {
1141 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1142 if (TNY_IS_HEADER (header)) {
1143 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1144 modest_window_mgr_unregister_header (mgr, header);
1146 g_object_unref (priv->draft_msg);
1147 priv->draft_msg = NULL;
1149 if (priv->outbox_msg != NULL) {
1150 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1151 if (TNY_IS_HEADER (header)) {
1152 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1153 modest_window_mgr_unregister_header (mgr, header);
1155 g_object_unref (priv->outbox_msg);
1156 priv->outbox_msg = NULL;
1158 if (priv->correct_scroll_idle > 0) {
1159 g_source_remove (priv->correct_scroll_idle);
1160 priv->correct_scroll_idle = 0;
1162 if (priv->scroll_drag_timeout_id > 0) {
1163 g_source_remove (priv->scroll_drag_timeout_id);
1164 priv->scroll_drag_timeout_id = 0;
1166 if (priv->clipboard_owner_idle > 0) {
1167 g_source_remove (priv->clipboard_owner_idle);
1168 priv->clipboard_owner_idle = 0;
1170 if (priv->original_account_name)
1171 g_free (priv->original_account_name);
1172 if (priv->original_mailbox)
1173 g_free (priv->original_mailbox);
1174 g_free (priv->msg_uid);
1175 g_free (priv->last_search);
1176 g_slist_free (priv->font_items_group);
1177 g_free (priv->references);
1178 g_free (priv->in_reply_to);
1179 g_object_unref (priv->attachments);
1180 g_object_unref (priv->images);
1182 /* This had to stay alive for as long as the picker that used it: */
1183 modest_pair_list_free (priv->from_field_protos);
1185 G_OBJECT_CLASS(parent_class)->finalize (obj);
1189 pixbuf_size_prepared (GdkPixbufLoader *loader,
1192 ModestMsgEditWindow *self)
1194 gint new_height, new_width;
1197 new_height = height;
1201 if (width > IMAGE_MAX_WIDTH) {
1202 new_height = height * IMAGE_MAX_WIDTH / width;
1203 new_width = IMAGE_MAX_WIDTH;
1206 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1210 pixbuf_from_stream (TnyStream *stream,
1211 const gchar *mime_type,
1212 guint64 *stream_size,
1213 ModestMsgEditWindow *self)
1215 GdkPixbufLoader *loader;
1218 GError *error = NULL;
1222 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1224 if (loader == NULL) {
1229 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1231 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1233 tny_stream_reset (TNY_STREAM (stream));
1234 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1235 unsigned char read_buffer[128];
1237 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1239 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1242 /* Allow some UI responsiveness */
1243 while (gtk_events_pending ())
1244 gtk_main_iteration ();
1246 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1248 gdk_pixbuf_loader_close (loader, &error);
1251 g_error_free (error);
1252 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1254 g_object_ref (pixbuf);
1255 g_object_unref (loader);
1260 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1261 GdkPixbuf *new_pixbuf;
1263 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1264 gdk_pixbuf_get_width (pixbuf);
1265 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1266 g_object_unref (pixbuf);
1267 pixbuf = new_pixbuf;
1271 *stream_size = size;
1277 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1279 ModestMsgEditWindowPrivate *priv;
1282 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1284 g_object_ref (self);
1285 for (iter = tny_list_create_iterator (attachments);
1286 !tny_iterator_is_done (iter);
1287 tny_iterator_next (iter)) {
1288 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1289 const gchar *cid = tny_mime_part_get_content_id (part);
1290 const gchar *mime_type = tny_mime_part_get_content_type (part);
1291 if ((cid != NULL)&&(mime_type != NULL)) {
1292 guint64 stream_size;
1293 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1294 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1297 g_object_unref (stream);
1299 if (pixbuf != NULL) {
1300 priv->images_count ++;
1301 priv->images_size += stream_size;
1302 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1303 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1305 g_object_unref (pixbuf);
1308 g_object_unref (part);
1310 g_object_unref (iter);
1311 g_object_unref (self);
1315 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1317 TnyMimePart *parent = NULL;
1318 const gchar *content_type = NULL;
1319 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1321 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1323 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1324 parent = g_object_ref (msg);
1325 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1326 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1329 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1330 iter = tny_list_create_iterator (parts);
1331 while (!tny_iterator_is_done (iter)) {
1333 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1334 content_type = tny_mime_part_get_content_type (part);
1335 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1339 g_object_unref (part);
1341 tny_iterator_next (iter);
1343 g_object_unref (iter);
1344 g_object_unref (parts);
1347 if (parent != NULL) {
1348 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1351 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1352 iter = tny_list_create_iterator (parts);
1353 while (!tny_iterator_is_done (iter)) {
1355 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1356 content_type = tny_mime_part_get_content_type (part);
1357 if (content_type && g_str_has_prefix (content_type, "image/")) {
1358 tny_list_prepend (priv->images, (GObject *) part);
1360 g_object_unref (part);
1361 tny_iterator_next (iter);
1363 g_object_unref (iter);
1364 g_object_unref (parts);
1365 g_object_unref (parent);
1370 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1373 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1375 for (iter = tny_list_create_iterator (attachments) ;
1376 !tny_iterator_is_done (iter);
1377 tny_iterator_next (iter)) {
1378 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1379 const gchar *cid = tny_mime_part_get_content_id (part);
1381 char *invalid = NULL;
1382 gint int_cid = strtol (cid, &invalid, 10);
1383 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1384 priv->next_cid = int_cid + 1;
1387 g_object_unref (part);
1389 g_object_unref (iter);
1393 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1396 gchar *to, *cc, *bcc, *subject;
1398 ModestMsgEditWindowPrivate *priv;
1399 ModestWindowPrivate *parent_priv;
1401 TnyHeaderFlags priority_flags;
1402 TnyFolder *msg_folder;
1403 gboolean is_html = FALSE;
1404 gboolean field_view_set;
1405 TnyList *orig_header_pairs;
1407 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1408 g_return_if_fail (TNY_IS_MSG (msg));
1410 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1411 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1413 header = tny_msg_get_header (msg);
1414 to = tny_header_dup_to (header);
1415 cc = tny_header_dup_cc (header);
1416 bcc = tny_header_dup_bcc (header);
1417 subject = tny_header_dup_subject (header);
1419 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1420 priority_flags = tny_header_get_priority (header);
1423 gchar *quoted_names = modest_text_utils_quote_names (to);
1424 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1425 g_free (quoted_names);
1428 field_view_set = TRUE;
1430 gchar *quoted_names = modest_text_utils_quote_names (cc);
1431 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1432 g_free (quoted_names);
1433 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1434 gtk_widget_show (priv->cc_caption);
1435 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1436 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1437 gtk_widget_hide (priv->cc_caption);
1438 field_view_set = FALSE;
1440 modest_togglable_set_active (priv->cc_button, field_view_set);
1442 field_view_set = TRUE;
1444 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1445 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1446 g_free (quoted_names);
1447 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1448 gtk_widget_show (priv->bcc_caption);
1449 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1450 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1451 gtk_widget_hide (priv->bcc_caption);
1452 field_view_set = FALSE;
1454 modest_togglable_set_active (priv->bcc_button, field_view_set);
1458 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1459 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1462 update_window_title (self);
1464 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1465 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1467 if ((body == NULL)||(body[0] == '\0')) {
1469 body = modest_text_utils_convert_to_html ("");
1472 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1473 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1476 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1479 /* Add attachments to the view */
1480 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1481 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1482 if (tny_list_get_length (priv->attachments) == 0) {
1483 gtk_widget_hide (priv->attachments_caption);
1485 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1486 gtk_widget_show_all (priv->attachments_caption);
1488 get_related_images (self, msg);
1489 update_next_cid (self, priv->attachments);
1490 update_next_cid (self, priv->images);
1491 replace_with_images (self, priv->images);
1493 if (preserve_is_rich && !is_html) {
1494 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1495 /* Get the default format required from configuration */
1496 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1497 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1500 /* Set the default focus depending on having already a To: field or not */
1501 if ((!to)||(*to == '\0')) {
1502 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1504 gtk_widget_grab_focus (priv->msg_body);
1507 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1509 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1510 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1512 modest_msg_edit_window_set_modified (self, FALSE);
1514 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1515 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1516 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1517 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1519 if (priv->msg_uid) {
1520 g_free (priv->msg_uid);
1521 priv->msg_uid = NULL;
1524 /* we should set a reference to the incoming message if it is a draft */
1525 msg_folder = tny_msg_get_folder (msg);
1527 if (modest_tny_folder_is_local_folder (msg_folder)) {
1528 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1529 if (type == TNY_FOLDER_TYPE_INVALID)
1530 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1532 if (type == TNY_FOLDER_TYPE_DRAFTS)
1533 priv->draft_msg = g_object_ref(msg);
1534 if (type == TNY_FOLDER_TYPE_OUTBOX)
1535 priv->outbox_msg = g_object_ref(msg);
1536 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1538 g_object_unref (msg_folder);
1541 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1542 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1543 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1544 g_object_unref (orig_header_pairs);
1552 #ifndef MODEST_TOOLKIT_HILDON2
1554 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1557 GList *item_children, *node;
1558 GtkWidget *bin_child;
1560 bin_child = gtk_bin_get_child (GTK_BIN(item));
1562 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1564 for (node = item_children; node != NULL; node = g_list_next (node)) {
1565 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1566 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1569 g_list_free (item_children);
1573 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1576 GList *item_children, *node;
1578 box = gtk_bin_get_child (GTK_BIN (item));
1579 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1580 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1582 for (node = item_children; node != NULL; node = g_list_next (node)) {
1583 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1584 if (GTK_IS_TOGGLE_BUTTON (node->data))
1585 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1586 else if (GTK_IS_BUTTON (node->data))
1587 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1589 g_list_free (item_children);
1594 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1596 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1597 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1598 GtkWidget *placeholder;
1599 GtkWidget *tool_item;
1604 GtkWidget *sizes_menu;
1608 #ifndef MODEST_TOOLKIT_HILDON2
1609 GSList *radio_group, *node;
1610 GtkWidget *fonts_menu;
1614 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1615 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1616 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1617 #ifdef MODEST_TOOLKIT_HILDON2
1618 HILDON_ICON_SIZE_FINGER
1620 GTK_ICON_SIZE_LARGE_TOOLBAR
1623 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1625 /* Font color placeholder */
1626 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1627 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1630 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1631 #ifdef MODEST_TOOLKIT_HILDON2
1632 priv->font_color_button = modest_color_button_new ();
1634 priv->font_color_button = gtk_color_button_new ();
1636 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1637 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1638 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1639 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1640 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1641 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1642 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1643 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1645 G_CALLBACK (modest_msg_edit_window_color_button_change),
1648 /* Font size and face placeholder */
1649 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1650 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1652 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1653 priv->size_tool_button_label = gtk_label_new (NULL);
1654 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1655 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1656 size_text, "</span>", NULL);
1657 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1658 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1660 #ifdef MODEST_TOOLKIT_HILDON2
1661 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1663 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1664 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1665 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1666 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1667 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1668 gtk_widget_set_sensitive (arrow, FALSE);
1669 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1670 sizes_menu = gtk_menu_new ();
1671 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1672 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1675 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1676 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1678 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1682 if (wp_font_size[size_index] == 12)
1683 priv->current_size_index = size_index;
1687 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1688 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1689 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1690 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1691 priv->font_size_toolitem = tool_item;
1693 #ifdef MODEST_TOOLKIT_HILDON2
1695 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1696 priv->font_tool_button_label = gtk_label_new (NULL);
1697 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1698 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1699 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1701 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1702 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1703 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1704 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1705 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1706 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1707 gtk_widget_set_sensitive (arrow, FALSE);
1708 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1710 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1711 priv->font_tool_button_label = gtk_label_new (NULL);
1712 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1713 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1715 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1716 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1717 gtk_widget_show (priv->font_tool_button_label);
1718 gtk_widget_show (GTK_WIDGET (tool_item));
1719 fonts_menu = gtk_menu_new ();
1722 #ifdef MODEST_TOOLKIT_HILDON2
1723 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1724 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1727 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1729 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1730 0, wp_get_font_name (font_index),
1733 if (font_index == DEFAULT_FONT)
1734 priv->current_face_index = font_index;
1736 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1737 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1738 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1739 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1740 priv->font_face_toolitem = tool_item;
1742 priv->font_items_group = NULL;
1744 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1745 GtkWidget *font_menu_item;
1746 GtkWidget *child_label;
1748 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1749 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1750 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1751 wp_get_font_name (font_index), "</span>", NULL);
1752 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1755 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1756 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1757 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1758 gtk_widget_show (font_menu_item);
1760 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1763 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1764 GtkWidget *item = (GtkWidget *) node->data;
1765 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1768 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1769 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1770 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1771 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1772 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1773 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1774 priv->font_face_toolitem = tool_item;
1777 /* Set expand and homogeneous for remaining items */
1778 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1779 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1780 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1781 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1782 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1783 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1784 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1785 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1786 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1788 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1789 will not show the tool items added to the placeholders) */
1790 gtk_widget_show_all (parent_priv->toolbar);
1792 /* Set the no show all *after* showing all items. We do not
1793 want the toolbar to be shown with a show all because it
1794 could go against the gconf setting regarding showing or not
1795 the toolbar of the editor window */
1796 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1802 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1805 ModestWindowPrivate *parent_priv;
1806 ModestMsgEditWindowPrivate *priv;
1807 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1808 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1809 ModestWindowMgr *mgr = NULL;
1811 g_return_val_if_fail (msg, NULL);
1812 g_return_val_if_fail (account_name, NULL);
1814 mgr = modest_runtime_get_window_mgr ();
1816 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1819 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1821 /* Menubar. Update the state of some toggles */
1822 priv->from_field_protos = get_transports ();
1823 priv->original_mailbox = NULL;
1824 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1825 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1826 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1827 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1828 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1829 priv->original_mailbox = g_strdup (mailbox);
1830 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1831 /* We set the first mailbox as the active mailbox */
1832 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1833 if (priv->original_mailbox != NULL)
1834 modest_selector_set_active_id (priv->from_field,
1835 (gpointer) priv->original_mailbox);
1837 modest_selector_set_active_id (priv->from_field,
1838 (gpointer) account_name);
1840 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1842 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1843 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1844 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1845 #ifdef HILDON_TOOLKIT_HILDON2
1846 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1848 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1849 hildon_touch_selector_get_current_text
1850 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1853 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1854 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1857 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1859 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1861 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1862 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1864 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1866 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1867 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1868 /* Add common dimming rules */
1869 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1870 modest_msg_edit_window_toolbar_dimming_entries,
1871 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1872 MODEST_WINDOW (obj));
1873 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_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->font_size_toolitem,
1877 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1878 MODEST_WINDOW (obj));
1879 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1880 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1881 MODEST_WINDOW (obj));
1882 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1883 G_CALLBACK (modest_ui_dimming_rules_on_send),
1884 MODEST_WINDOW (obj));
1885 /* Insert dimming rules group for this window */
1886 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1887 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1889 /* Setup app menu */
1890 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1892 /* Checks the dimming rules */
1893 g_object_unref (toolbar_rules_group);
1894 g_object_unref (clipboard_rules_group);
1895 gtk_widget_hide (priv->priority_icon);
1896 gtk_widget_queue_resize (priv->subject_box);
1897 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1899 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1901 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1902 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1903 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1904 priv->update_caption_visibility = TRUE;
1906 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1908 /* Track account-removed signal, this window should be closed
1909 in the case we're creating a mail associated to the account
1911 priv->account_removed_handler_id =
1912 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1914 G_CALLBACK(on_account_removed),
1917 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1919 return (ModestWindow*) obj;
1923 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1925 GString **string_buffer = (GString **) user_data;
1927 *string_buffer = g_string_append (*string_buffer, buffer);
1933 * @result: A new string which should be freed with g_free().
1936 get_formatted_data (ModestMsgEditWindow *edit_window)
1938 ModestMsgEditWindowPrivate *priv;
1939 GString *string_buffer = g_string_new ("");
1941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1943 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1945 modest_text_utils_hyperlinkify (string_buffer);
1947 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1949 return g_string_free (string_buffer, FALSE);
1954 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1957 const gchar *account_name;
1958 ModestMsgEditWindowPrivate *priv;
1959 TnyIterator *att_iter;
1960 const gchar *picker_active_id;
1962 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1966 picker_active_id = modest_selector_get_active_id (priv->from_field);
1967 g_return_val_if_fail (picker_active_id, NULL);
1968 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1970 /* don't free these (except from) */
1971 data = g_slice_new0 (MsgData);
1972 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1973 data->account_name = g_strdup (account_name);
1974 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1975 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1976 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1977 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1978 data->references = g_strdup (priv->references);
1979 data->in_reply_to = g_strdup (priv->in_reply_to);
1980 if (priv->draft_msg) {
1981 data->draft_msg = g_object_ref (priv->draft_msg);
1982 } else if (priv->outbox_msg) {
1983 data->draft_msg = g_object_ref (priv->outbox_msg);
1985 data->draft_msg = NULL;
1988 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1990 gtk_text_buffer_get_bounds (buf, &b, &e);
1991 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1993 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1994 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1996 data->html_body = NULL;
1998 /* deep-copy the data */
1999 att_iter = tny_list_create_iterator (priv->attachments);
2000 data->attachments = NULL;
2001 while (!tny_iterator_is_done (att_iter)) {
2002 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2003 if (!(TNY_IS_MIME_PART(part))) {
2004 g_warning ("strange data in attachment list");
2005 g_object_unref (part);
2006 tny_iterator_next (att_iter);
2009 data->attachments = g_list_append (data->attachments,
2011 tny_iterator_next (att_iter);
2013 g_object_unref (att_iter);
2015 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
2016 att_iter = tny_list_create_iterator (priv->images);
2017 data->images = NULL;
2018 while (!tny_iterator_is_done (att_iter)) {
2019 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2021 if (!(TNY_IS_MIME_PART(part))) {
2022 g_warning ("strange data in attachment list");
2023 g_object_unref (part);
2024 tny_iterator_next (att_iter);
2027 cid = tny_mime_part_get_content_id (part);
2029 gchar *image_tag_id;
2030 GtkTextTag *image_tag;
2032 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2033 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2034 g_free (image_tag_id);
2036 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2038 ((gtk_text_iter_has_tag (&iter, image_tag))||
2039 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2040 data->images = g_list_append (data->images,
2041 g_object_ref (part));
2043 g_object_unref (part);
2044 tny_iterator_next (att_iter);
2046 g_object_unref (att_iter);
2048 data->priority_flags = priv->priority_flags;
2049 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
2056 unref_gobject (GObject *obj, gpointer data)
2058 if (!G_IS_OBJECT(obj))
2060 g_object_unref (obj);
2064 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2067 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2075 g_free (data->from);
2076 g_free (data->subject);
2077 g_free (data->plain_body);
2078 g_free (data->html_body);
2079 g_free (data->account_name);
2080 g_free (data->references);
2081 g_free (data->in_reply_to);
2083 g_object_unref (data->custom_header_pairs);
2085 if (data->draft_msg != NULL) {
2086 g_object_unref (data->draft_msg);
2087 data->draft_msg = NULL;
2090 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2091 g_list_free (data->attachments);
2092 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2093 g_list_free (data->images);
2095 g_slice_free (MsgData, data);
2099 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2101 guint64 *parts_size)
2103 ModestMsgEditWindowPrivate *priv;
2105 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2107 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2109 /* TODO: add images */
2110 *parts_size += priv->images_size;
2111 *parts_count += priv->images_count;
2116 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2119 ModestMsgEditWindowPrivate *priv = NULL;
2120 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2122 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2124 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2126 return MODEST_MSG_EDIT_FORMAT_HTML;
2128 return MODEST_MSG_EDIT_FORMAT_TEXT;
2132 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2133 ModestMsgEditFormat format)
2135 ModestMsgEditWindowPrivate *priv;
2136 ModestWindowPrivate *parent_priv;
2138 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2139 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2140 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2143 case MODEST_MSG_EDIT_FORMAT_HTML:
2144 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2145 update_signature (self, priv->last_from_account, priv->last_from_account);
2146 if (parent_priv->toolbar)
2147 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2148 MODEST_MSG_EDIT_WINDOW (self));
2150 case MODEST_MSG_EDIT_FORMAT_TEXT:
2151 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2152 if (parent_priv->toolbar)
2153 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2154 MODEST_MSG_EDIT_WINDOW (self));
2157 g_return_if_reached ();
2161 ModestMsgEditFormatState *
2162 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2164 ModestMsgEditFormatState *format_state = NULL;
2165 ModestMsgEditWindowPrivate *priv;
2166 WPTextBufferFormat *buffer_format;
2168 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2170 buffer_format = g_new0 (WPTextBufferFormat, 1);
2171 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2173 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2175 format_state = g_new0 (ModestMsgEditFormatState, 1);
2176 format_state->bold = buffer_format->bold&0x1;
2177 format_state->italics = buffer_format->italic&0x1;
2178 format_state->bullet = buffer_format->bullet&0x1;
2179 format_state->color = buffer_format->color;
2180 format_state->font_size = buffer_format->font_size;
2181 format_state->font_family = wp_get_font_name (buffer_format->font);
2182 format_state->justification = buffer_format->justification;
2183 g_free (buffer_format);
2185 return format_state;
2190 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2191 const ModestMsgEditFormatState *format_state)
2193 ModestMsgEditWindowPrivate *priv;
2194 WPTextBufferFormat *buffer_format;
2195 WPTextBufferFormat *current_format;
2197 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2198 g_return_if_fail (format_state != NULL);
2200 buffer_format = g_new0 (WPTextBufferFormat, 1);
2201 current_format = g_new0 (WPTextBufferFormat, 1);
2203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2204 gtk_widget_grab_focus (priv->msg_body);
2205 buffer_format->bold = (format_state->bold != FALSE);
2206 buffer_format->italic = (format_state->italics != FALSE);
2207 buffer_format->color = format_state->color;
2208 buffer_format->font_size = format_state->font_size;
2209 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2210 buffer_format->justification = format_state->justification;
2211 buffer_format->bullet = format_state->bullet;
2213 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2215 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2216 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2217 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2218 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2219 buffer_format->cs.font = (buffer_format->font != current_format->font);
2220 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2221 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2223 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2224 if (buffer_format->cs.bold) {
2225 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2226 GINT_TO_POINTER (buffer_format->bold&0x1));
2228 if (buffer_format->cs.italic) {
2229 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2230 GINT_TO_POINTER (buffer_format->italic&0x1));
2232 if (buffer_format->cs.color) {
2233 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2234 GINT_TO_POINTER (&(buffer_format->color)));
2236 if (buffer_format->cs.font_size) {
2237 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2238 GINT_TO_POINTER (buffer_format->font_size));
2240 if (buffer_format->cs.justification) {
2241 switch (buffer_format->justification) {
2242 case GTK_JUSTIFY_LEFT:
2243 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2244 GINT_TO_POINTER(TRUE));
2246 case GTK_JUSTIFY_CENTER:
2247 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2248 GINT_TO_POINTER(TRUE));
2250 case GTK_JUSTIFY_RIGHT:
2251 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2252 GINT_TO_POINTER(TRUE));
2259 if (buffer_format->cs.font) {
2260 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2261 GINT_TO_POINTER (buffer_format->font));
2263 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2264 if (buffer_format->cs.bullet) {
2265 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2266 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2268 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2270 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2272 g_free (buffer_format);
2273 g_free (current_format);
2275 /* Check dimming rules */
2276 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2277 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2281 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2283 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2285 ModestWindowPrivate *parent_priv;
2286 ModestMsgEditWindowPrivate *priv;
2288 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2289 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2291 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2292 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2293 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2294 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2296 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2297 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2298 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2301 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2303 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2304 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2306 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2307 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2309 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2310 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2313 switch (buffer_format->justification)
2315 case GTK_JUSTIFY_LEFT:
2316 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2318 case GTK_JUSTIFY_CENTER:
2319 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2321 case GTK_JUSTIFY_RIGHT:
2322 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2329 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2331 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2332 G_CALLBACK (modest_msg_edit_window_color_button_change),
2334 #ifdef MODEST_TOOLKIT_HILDON2
2335 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2337 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2339 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2340 G_CALLBACK (modest_msg_edit_window_color_button_change),
2343 if (priv->current_size_index != buffer_format->font_size) {
2347 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2348 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2352 priv->current_size_index = buffer_format->font_size;
2354 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2355 markup = g_strconcat ("<span font_family='Sans'>",
2356 size_text, "</span>", NULL);
2358 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2362 gtk_tree_path_free (path);
2365 #ifdef MODEST_TOOLKIT_HILDON2
2366 if (priv->current_face_index != buffer_format->font) {
2370 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2371 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2375 priv->current_face_index = buffer_format->font;
2376 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2377 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2378 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2385 GtkWidget *new_font_menuitem;
2386 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2387 buffer_format->font))->data);
2388 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2392 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2393 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2394 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2396 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2397 G_CALLBACK (modest_msg_edit_window_font_change),
2399 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2400 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2401 G_CALLBACK (modest_msg_edit_window_font_change),
2406 g_free (buffer_format);
2412 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2414 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2415 ModestMsgEditWindowPrivate *priv;
2416 GtkWidget *dialog = NULL;
2418 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2419 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2421 #ifdef MODEST_TOOLKIT_HILDON2
2422 dialog = hildon_color_chooser_new ();
2423 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2424 g_free (buffer_format);
2426 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2428 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2429 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2432 gtk_widget_destroy (dialog);
2434 dialog = gtk_color_selection_dialog_new (NULL);
2435 GtkWidget *selection;
2437 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2438 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2439 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2440 g_free (buffer_format);
2442 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2444 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2445 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2448 gtk_widget_destroy (dialog);
2455 create_stream_for_uri (const gchar* uri)
2460 TnyStream *result = NULL;
2462 GnomeVFSHandle *handle = NULL;
2463 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2464 if (test == GNOME_VFS_OK) {
2465 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2466 /* Streams over OBEX (Bluetooth) are not seekable but
2467 * we expect them to be (we might need to read them
2468 * several times). So if this is a Bluetooth URI just
2469 * read the whole file into memory (this is not a fast
2470 * protocol so we can assume that these files are not
2471 * going to be very big) */
2472 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2473 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2474 TnyStream *memstream = tny_camel_mem_stream_new ();
2475 tny_stream_write_to_stream (vfssstream, memstream);
2476 g_object_unref (vfssstream);
2479 result = vfssstream;
2487 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2490 ModestMsgEditWindowPrivate *priv;
2491 GtkWidget *dialog = NULL;
2493 GSList *uris = NULL;
2494 GSList *uri_node = NULL;
2496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2498 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2499 _("mcen_ia_select_inline_image_title"),
2500 (GtkWindow *) window,
2501 GTK_FILE_CHOOSER_ACTION_OPEN);
2502 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2504 #ifdef MODEST_TOOLKIT_HILDON2
2505 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2508 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2509 GTK_WINDOW (dialog), GTK_WINDOW (window));
2511 response = gtk_dialog_run (GTK_DIALOG (dialog));
2513 case GTK_RESPONSE_OK:
2515 gchar *current_folder;
2516 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2517 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2518 if (current_folder && current_folder != '\0') {
2520 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2521 current_folder, &err);
2523 g_debug ("Error storing latest used folder: %s", err->message);
2527 g_free (current_folder);
2533 gtk_widget_destroy (dialog);
2535 g_object_ref (window);
2536 /* The operation could take some time so allow the dialog to be closed */
2537 while (gtk_events_pending ())
2538 gtk_main_iteration ();
2540 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2542 GnomeVFSHandle *handle = NULL;
2543 GnomeVFSResult result;
2544 GtkTextIter position;
2545 GtkTextMark *insert_mark;
2547 uri = (const gchar *) uri_node->data;
2548 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2549 if (result == GNOME_VFS_OK) {
2551 GnomeVFSFileInfo *info;
2552 gchar *filename, *basename, *escaped_filename;
2553 TnyMimePart *mime_part;
2555 const gchar *mime_type = NULL;
2556 GnomeVFSURI *vfs_uri;
2557 guint64 stream_size;
2559 gnome_vfs_close (handle);
2560 vfs_uri = gnome_vfs_uri_new (uri);
2562 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2563 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2564 g_free (escaped_filename);
2565 gnome_vfs_uri_unref (vfs_uri);
2566 info = gnome_vfs_file_info_new ();
2568 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2569 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2571 mime_type = gnome_vfs_file_info_get_mime_type (info);
2573 mime_part = tny_platform_factory_new_mime_part
2574 (modest_runtime_get_platform_factory ());
2576 TnyStream *stream = create_stream_for_uri (uri);
2578 if (stream == NULL) {
2580 modest_platform_information_banner (NULL, NULL,
2581 _FM_OPENING_NOT_ALLOWED);
2583 g_object_unref (mime_part);
2584 gnome_vfs_file_info_unref (info);
2588 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2590 content_id = g_strdup_printf ("%d", priv->next_cid);
2591 tny_mime_part_set_content_id (mime_part, content_id);
2592 g_free (content_id);
2595 basename = g_path_get_basename (filename);
2596 tny_mime_part_set_filename (mime_part, basename);
2599 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2601 if (pixbuf != NULL) {
2602 priv->images_size += stream_size;
2603 priv->images_count ++;
2604 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2605 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2606 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2607 tny_mime_part_get_content_id (mime_part), pixbuf);
2608 g_object_unref (pixbuf);
2610 tny_list_prepend (priv->images, (GObject *) mime_part);
2611 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2613 modest_platform_information_banner (NULL, NULL,
2614 _("mail_ib_file_operation_failed"));
2618 g_object_unref (mime_part);
2619 gnome_vfs_file_info_unref (info);
2623 g_object_unref (window);
2627 on_attach_file_response (GtkDialog *dialog,
2631 GSList *uris = NULL;
2633 GnomeVFSFileSize total_size, allowed_size;
2634 ModestMsgEditWindow *window;
2635 ModestMsgEditWindowPrivate *priv;
2640 case GTK_RESPONSE_OK:
2642 gchar *current_folder;
2644 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2645 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2646 if (current_folder && current_folder != '\0') {
2648 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2649 current_folder, &err);
2651 g_debug ("Error storing latest used folder: %s", err->message);
2655 g_free (current_folder);
2662 window = MODEST_MSG_EDIT_WINDOW (user_data);
2663 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2665 /* allowed size is the maximum size - what's already there */
2666 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2667 &att_num, &att_size);
2668 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2671 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2673 const gchar *uri = (const gchar *) uri_node->data;
2676 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2678 if (total_size > allowed_size) {
2679 g_debug ("%s: total size: %u",
2680 __FUNCTION__, (unsigned int)total_size);
2683 allowed_size -= total_size;
2685 g_slist_foreach (uris, (GFunc) g_free, NULL);
2686 g_slist_free (uris);
2688 gtk_widget_destroy (GTK_WIDGET (dialog));
2692 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2694 GtkWidget *dialog = NULL;
2695 ModestMsgEditWindowPrivate *priv;
2698 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2700 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2702 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2705 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2706 _("mcen_ia_select_attachment_title"),
2707 (GtkWindow *) window,
2708 GTK_FILE_CHOOSER_ACTION_OPEN);
2709 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2710 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2711 if (conf_folder && conf_folder[0] != '\0') {
2712 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2715 /* Set the default folder to documents folder */
2716 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2717 #ifdef MODEST_TOOLKIT_HILDON2
2720 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2721 ".documents", NULL);
2724 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2725 g_free (docs_folder);
2727 g_free (conf_folder);
2728 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2729 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2730 GTK_WINDOW (dialog), GTK_WINDOW (window));
2732 /* Connect to response & show */
2733 g_signal_connect (dialog, "response",
2734 G_CALLBACK (on_attach_file_response), window);
2735 gtk_widget_show (dialog);
2740 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2742 GnomeVFSFileSize allowed_size)
2745 GnomeVFSHandle *handle = NULL;
2746 ModestMsgEditWindowPrivate *priv;
2747 GnomeVFSResult result;
2748 GnomeVFSFileSize size = 0;
2749 g_return_val_if_fail (window, 0);
2750 g_return_val_if_fail (uri, 0);
2752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2754 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2755 if (result == GNOME_VFS_OK) {
2756 TnyMimePart *mime_part;
2758 const gchar *mime_type = NULL;
2760 gchar *escaped_filename;
2763 GnomeVFSFileInfo *info;
2764 GnomeVFSURI *vfs_uri;
2766 gnome_vfs_close (handle);
2767 vfs_uri = gnome_vfs_uri_new (uri);
2770 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2771 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2772 g_free (escaped_filename);
2773 gnome_vfs_uri_unref (vfs_uri);
2775 info = gnome_vfs_file_info_new ();
2777 if (gnome_vfs_get_file_info (uri,
2779 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2781 mime_type = gnome_vfs_file_info_get_mime_type (info);
2782 mime_part = tny_platform_factory_new_mime_part
2783 (modest_runtime_get_platform_factory ());
2785 /* try to get the attachment's size; this may fail for weird
2786 * file systems, like obex, upnp... */
2787 if (allowed_size != 0 &&
2788 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2790 if (size > allowed_size) {
2791 modest_platform_information_banner (NULL, NULL,
2792 _("mail_ib_error_attachment_size"));
2797 g_debug ("%s: could not get attachment size", __FUNCTION__);
2799 stream = create_stream_for_uri (uri);
2801 if (stream == NULL) {
2803 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2805 g_object_unref (mime_part);
2807 gnome_vfs_file_info_unref (info);
2811 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2812 g_object_unref (stream);
2814 content_id = g_strdup_printf ("%d", priv->next_cid);
2815 tny_mime_part_set_content_id (mime_part, content_id);
2816 g_free (content_id);
2819 basename = g_path_get_basename (filename);
2820 tny_mime_part_set_filename (mime_part, basename);
2823 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2824 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2826 info->size == 0, info->size);
2827 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2828 gtk_widget_show_all (priv->attachments_caption);
2829 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2831 g_object_unref (mime_part);
2832 gnome_vfs_file_info_unref (info);
2839 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2842 ModestMsgEditWindowPrivate *priv;
2845 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2848 if (att_list == NULL) {
2849 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2850 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2851 g_object_unref (att_list);
2855 g_object_ref (att_list);
2858 if (tny_list_get_length (att_list) == 0) {
2859 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2861 gboolean dialog_response;
2862 gchar *message = NULL;
2863 gchar *filename = NULL;
2865 if (tny_list_get_length (att_list) == 1) {
2867 iter = tny_list_create_iterator (att_list);
2868 part = (TnyMimePart *) tny_iterator_get_current (iter);
2869 g_object_unref (iter);
2870 if (TNY_IS_MSG (part)) {
2871 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2873 filename = tny_header_dup_subject (header);
2874 g_object_unref (header);
2876 if (filename == NULL) {
2877 filename = g_strdup (_("mail_va_no_subject"));
2880 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2882 g_object_unref (part);
2884 filename = g_strdup ("");
2886 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2887 "emev_nc_delete_attachments",
2888 tny_list_get_length (att_list)), filename);
2891 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2895 if (dialog_response != GTK_RESPONSE_OK) {
2896 g_object_unref (att_list);
2900 for (iter = tny_list_create_iterator (att_list);
2901 !tny_iterator_is_done (iter);
2902 tny_iterator_next (iter)) {
2903 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2904 const gchar *att_id;
2905 tny_list_remove (priv->attachments, (GObject *) mime_part);
2907 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2909 if (tny_list_get_length (priv->attachments) == 0)
2910 gtk_widget_hide (priv->attachments_caption);
2911 att_id = tny_mime_part_get_content_id (mime_part);
2913 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2915 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2916 g_object_unref (mime_part);
2918 g_object_unref (iter);
2921 g_object_unref (att_list);
2923 /* if the last attachment has been removed, focus the Subject: field */
2924 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2925 gtk_widget_grab_focus (priv->subject_field);
2929 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2932 ModestMsgEditWindowPrivate *priv;
2935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2937 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2939 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2941 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2944 #ifndef MODEST_TOOLKIT_HILDON2
2946 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2949 ModestMsgEditWindowPrivate *priv;
2950 gint new_font_index;
2951 ModestMsgEditWindow *window;
2954 window = MODEST_MSG_EDIT_WINDOW (userdata);
2955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2956 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2958 if (gtk_check_menu_item_get_active (menu_item)) {
2961 label = gtk_bin_get_child (GTK_BIN (menu_item));
2963 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2965 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2966 GINT_TO_POINTER(new_font_index)))
2967 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2969 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2970 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2971 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2978 font_size_clicked (GtkToolButton *button,
2979 ModestMsgEditWindow *window)
2981 #ifdef MODEST_TOOLKIT_HILDON2
2982 ModestMsgEditWindowPrivate *priv;
2983 GtkWidget *selector, *dialog;
2985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 selector = hildon_touch_selector_new ();
2988 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2989 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2991 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2992 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2993 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2995 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2999 WPTextBufferFormat format;
3001 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3003 memset (&format, 0, sizeof (format));
3004 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
3006 format.cs.font_size = TRUE;
3007 format.cs.text_position = TRUE;
3008 format.cs.font = TRUE;
3009 format.font_size = new_index;
3010 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
3012 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
3013 GINT_TO_POINTER (new_index)))
3014 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3016 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3017 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
3018 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
3019 size_text, "</span>", NULL);
3021 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
3025 gtk_widget_destroy (dialog);
3027 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3031 #ifdef MODEST_TOOLKIT_HILDON2
3033 font_face_clicked (GtkToolButton *button,
3034 ModestMsgEditWindow *window)
3036 ModestMsgEditWindowPrivate *priv;
3037 GtkWidget *selector, *dialog;
3038 GtkCellRenderer *renderer;
3040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3042 selector = hildon_touch_selector_new ();
3043 renderer = gtk_cell_renderer_text_new ();
3044 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3045 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3046 renderer, "family", 0, "text", 0, NULL);
3047 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3049 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3050 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3051 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3053 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3054 gint new_font_index;
3058 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3059 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3060 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3064 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3066 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3067 GINT_TO_POINTER(new_font_index)))
3068 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3070 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3071 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3073 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3077 gtk_tree_path_free (path);
3080 gtk_widget_destroy (dialog);
3082 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3087 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3090 ModestMsgEditWindowPrivate *priv = NULL;
3091 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3093 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3094 if (!priv->update_caption_visibility)
3097 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3099 gtk_widget_show (priv->cc_caption);
3101 gtk_widget_hide (priv->cc_caption);
3103 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3107 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3110 ModestMsgEditWindowPrivate *priv = NULL;
3111 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3113 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3114 if (!priv->update_caption_visibility)
3117 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3119 gtk_widget_show (priv->bcc_caption);
3121 gtk_widget_hide (priv->bcc_caption);
3123 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3127 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3128 ModestRecptEditor *editor)
3130 ModestMsgEditWindowPrivate *priv;
3132 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3133 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3135 /* we check for low-mem; in that case, show a warning, and don't allow
3136 * for the addressbook
3138 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3141 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3143 if (editor == NULL) {
3144 GtkWidget *view_focus, *parent;
3145 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3147 /* This code should be kept in sync with ModestRecptEditor. The
3148 textview inside the recpt editor is the one that really gets the
3149 focus. As it's inside a scrolled window, and this one inside the
3150 hbox recpt editor inherits from, we'll need to go up in the
3151 hierarchy to know if the text view is part of the recpt editor
3152 or if it's a different text entry */
3153 parent = gtk_widget_get_parent (view_focus);
3154 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3155 editor = MODEST_RECPT_EDITOR (parent);
3158 editor = MODEST_RECPT_EDITOR (priv->to_field);
3161 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3165 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3167 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3169 modest_msg_edit_window_open_addressbook (window, NULL);
3173 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3174 gboolean show_toolbar)
3176 ModestWindowPrivate *parent_priv;
3177 ModestMsgEditWindowPrivate *priv;
3179 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3180 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3181 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3183 /* We can not just use the code of
3184 modest_msg_edit_window_setup_toolbar because it has a
3185 mixture of both initialization and creation code. */
3187 gint current_format;
3188 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3189 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3190 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3191 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3193 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3196 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3198 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3199 if (modest_togglable_get_active (priv->show_toolbar_button) != show_toolbar) {
3200 modest_togglable_set_active (priv->show_toolbar_button, show_toolbar);
3205 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3206 TnyHeaderFlags priority_flags)
3208 ModestMsgEditWindowPrivate *priv;
3209 ModestWindowPrivate *parent_priv;
3211 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3214 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3216 if (priv->priority_flags != priority_flags) {
3217 GtkAction *priority_action = NULL;
3219 priv->priority_flags = priority_flags;
3221 switch (priority_flags) {
3222 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3223 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3224 MODEST_HEADER_ICON_HIGH,
3225 #ifdef MODEST_TOOLKIT_HILDON2
3226 HILDON_ICON_SIZE_SMALL
3228 GTK_ICON_SIZE_BUTTON
3231 gtk_widget_show (priv->priority_icon);
3232 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3233 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3235 case TNY_HEADER_FLAG_LOW_PRIORITY:
3236 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3237 MODEST_HEADER_ICON_LOW,
3238 #ifdef MODEST_TOOLKIT_HILDON2
3239 HILDON_ICON_SIZE_SMALL
3241 GTK_ICON_SIZE_BUTTON
3244 gtk_widget_show (priv->priority_icon);
3245 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3246 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3249 gtk_widget_hide (priv->priority_icon);
3250 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3251 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3254 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3255 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3257 gtk_widget_queue_resize (priv->subject_box);
3261 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3264 ModestMsgEditWindowPrivate *priv;
3265 ModestWindowPrivate *parent_priv;
3266 gint current_format;
3268 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3270 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3271 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3273 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3274 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3276 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3278 if (current_format != file_format) {
3279 switch (file_format) {
3280 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3281 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3282 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3283 update_signature (window, priv->last_from_account, priv->last_from_account);
3284 if (parent_priv->toolbar)
3285 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3286 MODEST_MSG_EDIT_WINDOW (window));
3288 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3291 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3292 if (response == GTK_RESPONSE_OK) {
3293 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3294 if (parent_priv->toolbar)
3295 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3296 MODEST_MSG_EDIT_WINDOW (window));
3298 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3299 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3304 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3305 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3306 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3311 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3313 #ifdef MODEST_TOOLKIT_HILDON2
3315 ModestMsgEditWindowPrivate *priv;
3316 WPTextBufferFormat oldfmt, fmt;
3317 gint old_position = 0;
3321 GdkColor *color = NULL;
3322 gboolean bold, bold_set, italic, italic_set;
3323 gboolean underline, underline_set;
3324 gboolean strikethrough, strikethrough_set;
3325 gboolean position_set;
3326 gboolean font_size_set, font_set, color_set;
3329 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3330 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3332 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3333 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3334 GTK_WINDOW(dialog), GTK_WINDOW (window));
3336 /* First we get the currently selected font information */
3337 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3339 switch (oldfmt.text_position) {
3340 case TEXT_POSITION_NORMAL:
3343 case TEXT_POSITION_SUPERSCRIPT:
3351 g_object_set (G_OBJECT (dialog),
3352 "bold", oldfmt.bold != FALSE,
3353 "bold-set", !oldfmt.cs.bold,
3354 "underline", oldfmt.underline != FALSE,
3355 "underline-set", !oldfmt.cs.underline,
3356 "italic", oldfmt.italic != FALSE,
3357 "italic-set", !oldfmt.cs.italic,
3358 "strikethrough", oldfmt.strikethrough != FALSE,
3359 "strikethrough-set", !oldfmt.cs.strikethrough,
3360 "color", &oldfmt.color,
3361 "color-set", !oldfmt.cs.color,
3362 "size", wp_font_size[oldfmt.font_size],
3363 "size-set", !oldfmt.cs.font_size,
3364 "position", old_position,
3365 "position-set", !oldfmt.cs.text_position,
3366 "family", wp_get_font_name (oldfmt.font),
3367 "family-set", !oldfmt.cs.font,
3370 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3371 GTK_WINDOW (dialog), GTK_WINDOW (window));
3372 gtk_widget_show_all (dialog);
3373 priv->font_dialog = dialog;
3374 response = gtk_dialog_run (GTK_DIALOG (dialog));
3375 priv->font_dialog = NULL;
3376 if (response == GTK_RESPONSE_OK) {
3378 g_object_get( dialog,
3380 "bold-set", &bold_set,
3381 "underline", &underline,
3382 "underline-set", &underline_set,
3384 "italic-set", &italic_set,
3385 "strikethrough", &strikethrough,
3386 "strikethrough-set", &strikethrough_set,
3388 "color-set", &color_set,
3390 "size-set", &font_size_set,
3391 "family", &font_name,
3392 "family-set", &font_set,
3393 "position", &position,
3394 "position-set", &position_set,
3399 if (response == GTK_RESPONSE_OK) {
3400 memset(&fmt, 0, sizeof(fmt));
3406 fmt.italic = italic;
3407 fmt.cs.italic = TRUE;
3409 if (underline_set) {
3410 fmt.underline = underline;
3411 fmt.cs.underline = TRUE;
3413 if (strikethrough_set) {
3414 fmt.strikethrough = strikethrough;
3415 fmt.cs.strikethrough = TRUE;
3420 ? TEXT_POSITION_NORMAL
3421 : ( ( position == 1 )
3422 ? TEXT_POSITION_SUPERSCRIPT
3423 : TEXT_POSITION_SUBSCRIPT );
3424 fmt.cs.text_position = TRUE;
3425 fmt.font_size = oldfmt.font_size;
3429 fmt.cs.color = TRUE;
3432 fmt.font = wp_get_font_index(font_name,
3437 if (font_size_set) {
3438 fmt.cs.font_size = TRUE;
3439 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3441 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3442 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3444 gtk_widget_destroy (dialog);
3446 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3451 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3453 ModestMsgEditWindowPrivate *priv;
3454 ModestWindowPrivate *parent_priv;
3455 gboolean was_rich_text, is_rich_text;
3457 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3458 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3459 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3461 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3463 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3465 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3467 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3468 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3469 MODEST_MSG_EDIT_WINDOW (window));
3472 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3473 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3477 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3479 ModestMsgEditWindowPrivate *priv;
3481 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3484 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3486 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3487 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3492 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3494 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3496 priv->can_undo = can_undo;
3500 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3502 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3504 priv->can_redo = can_redo;
3508 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3510 ModestMsgEditWindowPrivate *priv;
3511 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3514 return priv->can_undo;
3518 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3520 ModestMsgEditWindowPrivate *priv;
3521 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3524 return priv->can_redo;
3529 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3532 GtkTextIter match_start, match_end;
3534 if (image_id == NULL)
3537 gtk_text_buffer_get_start_iter (buffer, &iter);
3539 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3540 GSList *tags = gtk_text_iter_get_tags (&match_start);
3542 for (node = tags; node != NULL; node = g_slist_next (node)) {
3543 GtkTextTag *tag = (GtkTextTag *) node->data;
3544 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3545 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3546 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3548 offset = gtk_text_iter_get_offset (&match_start);
3549 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3550 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3554 gtk_text_iter_forward_char (&iter);
3559 message_is_empty (ModestMsgEditWindow *window)
3561 ModestMsgEditWindowPrivate *priv = NULL;
3563 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3564 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3566 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3567 * so we can ignore markup.
3569 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3572 count = gtk_text_buffer_get_char_count (buf);
3578 msg_body_focus (GtkWidget *focus,
3579 GdkEventFocus *event,
3583 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3584 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3585 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3590 recpt_field_changed (GtkTextBuffer *buffer,
3591 ModestMsgEditWindow *editor)
3593 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3594 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3598 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3600 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3601 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3605 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3608 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3609 GtkTextBuffer *buffer;
3611 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3612 gtk_text_buffer_set_modified (buffer, modified);
3613 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3614 gtk_text_buffer_set_modified (buffer, modified);
3615 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3616 gtk_text_buffer_set_modified (buffer, modified);
3617 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3621 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3623 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3624 const char *account_name;
3625 GtkTextBuffer *buffer;
3627 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3628 if (gtk_text_buffer_get_modified (buffer))
3630 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3631 if (gtk_text_buffer_get_modified (buffer))
3633 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3634 if (gtk_text_buffer_get_modified (buffer))
3636 if (gtk_text_buffer_get_modified (priv->text_buffer))
3639 account_name = modest_selector_get_active_id (priv->from_field);
3640 if (priv->original_mailbox) {
3641 if (!account_name || strcmp (account_name, priv->original_mailbox))
3643 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3654 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3656 ModestMsgEditWindowPrivate *priv = NULL;
3657 GSList *address_list = NULL;
3658 gboolean no_to, no_cc, no_bcc;
3660 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3663 /* check if there's no recipient added */
3664 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3665 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3666 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3669 if (no_to && no_cc && no_bcc) {
3670 /* no recipient contents, then select contacts */
3671 modest_msg_edit_window_open_addressbook (window, NULL);
3676 g_object_ref (window);
3677 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3678 (add_to_addressbook) ? &address_list : NULL)) {
3679 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3680 g_object_unref (window);
3683 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3684 (add_to_addressbook) ? &address_list : NULL)) {
3685 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3686 g_object_unref (window);
3689 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3690 (add_to_addressbook) ? &address_list : NULL)) {
3691 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3692 g_object_unref (window);
3696 /* Add contacts to address book */
3697 if (add_to_addressbook && address_list)
3698 modest_address_book_add_address_list (address_list);
3700 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3701 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3702 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3703 g_object_unref (window);
3710 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3712 GSList *recipients = NULL;
3713 ModestMsgEditWindowPrivate *priv;
3714 gchar *joined, *after_remove, *to, *cc, *bcc;
3716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3718 /* First of all check names */
3719 if (!modest_msg_edit_window_check_names (self, FALSE))
3722 if (!modest_msg_edit_window_has_pending_addresses (self))
3725 /* Don't add the from obviously */
3726 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3727 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3728 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3730 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3735 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3738 recipients = modest_text_utils_split_addresses_list (after_remove);
3739 g_free (after_remove);
3742 /* Offer the user to add recipients to the address book */
3743 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3744 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3749 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3750 ModestMsgEditWindow *window)
3752 modest_msg_edit_window_offer_attach_file (window);
3756 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3758 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3760 return priv->clipboard_text;
3764 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3766 ModestMsgEditWindow *window)
3768 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3769 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3772 /* It could happen that the window was already closed */
3773 if (!GTK_WIDGET_VISIBLE (window))
3776 g_object_ref (window);
3777 text = gtk_clipboard_wait_for_text (selection_clipboard);
3779 if (priv->clipboard_text != NULL) {
3780 g_free (priv->clipboard_text);
3782 priv->clipboard_text = text;
3784 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3786 g_object_unref (window);
3789 static gboolean clipboard_owner_change_idle (gpointer userdata)
3791 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3792 ModestMsgEditWindowPrivate *priv;
3794 gdk_threads_enter ();
3795 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3796 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3798 priv->clipboard_owner_idle = 0;
3799 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3800 gdk_threads_leave ();
3806 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3808 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3809 if (priv->clipboard_owner_idle == 0) {
3810 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3811 clipboard_owner_change_idle,
3812 g_object_ref (window),
3818 subject_field_move_cursor (GtkEntry *entry,
3819 GtkMovementStep step,
3824 /* It could happen that the window was already closed */
3825 if (!GTK_WIDGET_VISIBLE (window))
3828 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3832 update_window_title (ModestMsgEditWindow *window)
3834 ModestMsgEditWindowPrivate *priv = NULL;
3835 const gchar *subject;
3837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3838 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3839 if (subject == NULL || subject[0] == '\0')
3840 subject = _("mail_va_new_email");
3842 modest_window_set_title (MODEST_WINDOW (window), subject);
3848 body_insert_text (GtkTextBuffer *buffer,
3849 GtkTextIter *location,
3852 ModestMsgEditWindow *window)
3854 GtkTextIter end_iter;
3861 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3863 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3865 offset = gtk_text_iter_get_offset (&end_iter);
3866 line = gtk_text_iter_get_line (&end_iter);
3870 while (text_offset < text + len) {
3871 if (*text_offset == '\n')
3873 if (text_lines + line >= MAX_BODY_LINES) {
3874 len = text_offset - text;
3880 utf8_len = g_utf8_strlen (text, len);
3882 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3883 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3884 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3889 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3891 /* Prevent endless recursion */
3892 result = g_strndup (text, utf8_end - text);
3893 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3894 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3895 (gpointer) result, (gpointer) (utf8_end - text),
3897 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3901 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3902 if (priv->max_chars_banner == NULL) {
3903 #ifdef MODEST_TOOLKIT_HILDON2
3904 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3905 _CS_MAXIMUM_CHARACTERS_REACHED);
3906 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3913 subject_field_changed (GtkEditable *editable,
3914 ModestMsgEditWindow *window)
3916 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3917 update_window_title (window);
3918 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3919 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3920 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3923 subject_field_insert_text (GtkEditable *editable,
3925 gint new_text_length,
3927 ModestMsgEditWindow *window)
3929 GString *result = g_string_new ("");
3931 gint result_len = 0;
3932 const gchar *entry_text = NULL;
3935 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3936 old_length = g_utf8_strlen (entry_text, -1);
3938 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3939 gunichar c = g_utf8_get_char_validated (current, 8);
3940 /* Invalid unichar, stop */
3946 result = g_string_append_unichar (result, c);
3950 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3951 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3954 /* Prevent endless recursion */
3955 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3956 g_signal_emit_by_name (editable, "insert-text",
3957 (gpointer) result->str, (gpointer) result->len,
3958 (gpointer) position, (gpointer) window);
3959 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3963 if (result_len + old_length > 1000) {
3964 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3965 _CS_MAXIMUM_CHARACTERS_REACHED);
3967 g_string_free (result, TRUE);
3971 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
3974 ModestMsgEditWindowPrivate *priv = NULL;
3976 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3977 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3979 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
3982 gtk_widget_show_all (priv->isearch_toolbar);
3983 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
3985 gtk_widget_hide_all (priv->isearch_toolbar);
3986 gtk_widget_grab_focus (priv->msg_body);
3991 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3993 GtkTextIter *match_start,
3994 GtkTextIter *match_end)
3996 GtkTextIter end_iter;
3997 gchar *str_casefold;
4000 gchar *range_casefold;
4003 gboolean result = FALSE;
4010 gtk_text_iter_forward_to_end (&end_iter);
4012 str_casefold = g_utf8_casefold (str, -1);
4013 str_chars_n = strlen (str);
4015 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
4016 range_casefold = g_utf8_casefold (range_text, -1);
4017 range_chars_n = strlen (range_casefold);
4019 if (range_chars_n < str_chars_n) {
4020 g_free (str_casefold);
4021 g_free (range_text);
4022 g_free (range_casefold);
4026 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
4027 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
4028 if (!g_utf8_collate (range_subtext, str_casefold)) {
4029 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
4031 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
4032 match_start, match_end, NULL)) {
4033 g_debug ("Matched string with collate, but not matched in model");
4035 g_free (found_text);
4037 g_free (range_subtext);
4041 g_free (str_casefold);
4042 g_free (range_text);
4043 g_free (range_casefold);
4050 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
4051 ModestMsgEditWindow *window)
4053 const gchar *current_search = NULL;
4054 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4056 GtkTextIter selection_start, selection_end;
4057 GtkTextIter match_start, match_end;
4058 gboolean continue_search = FALSE;
4060 if (message_is_empty (window)) {
4061 g_free (priv->last_search);
4062 priv->last_search = NULL;
4063 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
4067 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
4068 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
4069 g_free (priv->last_search);
4070 priv->last_search = NULL;
4071 /* Information banner about empty search */
4072 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
4076 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
4077 continue_search = TRUE;
4079 g_free (priv->last_search);
4080 priv->last_search = g_strdup (current_search);
4083 if (continue_search) {
4084 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
4085 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
4086 &match_start, &match_end);
4088 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
4090 GtkTextIter buffer_start;
4091 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
4092 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
4093 &match_start, &match_end);
4095 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
4098 /* Mark as selected the string found in search */
4100 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
4101 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
4102 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
4104 g_free (priv->last_search);
4105 priv->last_search = NULL;
4110 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
4112 ModestMsgEditWindowPrivate *priv;
4114 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4119 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
4122 ModestMsgEditWindowPrivate *priv;
4124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4129 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
4130 ModestMsgEditWindow *window)
4132 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
4136 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
4139 ModestMsgEditWindowPrivate *priv;
4140 TnyHeader *header = NULL;
4142 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4143 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
4145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4147 if (priv->draft_msg != NULL) {
4148 g_object_unref (priv->draft_msg);
4151 if (draft != NULL) {
4152 g_object_ref (draft);
4153 header = tny_msg_get_header (draft);
4154 if (priv->msg_uid) {
4155 g_free (priv->msg_uid);
4156 priv->msg_uid = NULL;
4158 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
4161 priv->draft_msg = draft;
4165 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
4166 GtkTextIter *start, GtkTextIter *end,
4169 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
4170 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
4173 if (tag == NULL) return;
4174 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
4175 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
4176 replace_with_images (window, priv->images);
4181 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
4184 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4186 g_return_if_fail (TNY_IS_MIME_PART (part));
4187 tny_list_prepend (priv->attachments, (GObject *) part);
4188 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4189 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4190 gtk_widget_show_all (priv->attachments_caption);
4191 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4195 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4197 ModestMsgEditWindowPrivate *priv;
4199 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4200 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4202 return priv->msg_uid;
4206 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4207 ModestMsgEditWindowWidgetType widget_type)
4209 ModestMsgEditWindowPrivate *priv;
4211 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4214 switch (widget_type) {
4215 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4216 return priv->msg_body;
4218 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4219 return priv->to_field;
4221 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4222 return priv->cc_field;
4224 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4225 return priv->bcc_field;
4227 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4228 return priv->subject_field;
4230 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4231 return priv->attachments_view;
4239 remove_tags (WPTextBuffer *buffer)
4241 GtkTextIter start, end;
4243 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4244 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4246 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4250 on_account_removed (TnyAccountStore *account_store,
4251 TnyAccount *account,
4254 /* Do nothing if it's a store account, because we use the
4255 transport to send the messages */
4256 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4257 const gchar *parent_acc = NULL;
4258 const gchar *our_acc = NULL;
4260 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4261 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4262 /* Close this window if I'm showing a message of the removed account */
4263 if (strcmp (parent_acc, our_acc) == 0)
4264 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4269 update_signature (ModestMsgEditWindow *self,
4270 const gchar *old_account,
4271 const gchar *new_account)
4273 ModestMsgEditWindowPrivate *priv;
4274 gboolean has_old_signature, has_new_signature;
4276 ModestAccountMgr *mgr;
4279 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4281 gtk_text_buffer_begin_user_action (priv->text_buffer);
4283 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4284 mgr = modest_runtime_get_account_mgr ();
4288 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4289 if (has_old_signature) {
4290 GtkTextIter match_start, match_end;
4292 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4293 seems that the search has some problems
4294 with the blank space at the end */
4295 if (gtk_text_iter_forward_search (&iter, "--",
4296 GTK_TEXT_SEARCH_TEXT_ONLY,
4297 &match_start, NULL, NULL)) {
4298 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4299 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4301 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4302 &match_start, &match_end, NULL)) {
4306 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4311 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4312 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4313 if (has_new_signature) {
4316 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4317 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4319 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4321 WPTextBufferFormat *fmt;
4322 GdkColor style_color;
4323 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4324 gdk_color_parse ("grey", &style_color);
4326 fmt = g_new0 (WPTextBufferFormat, 1);
4327 fmt->color = style_color;
4328 fmt->cs.color = 0x1;
4329 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4333 g_free (full_signature);
4335 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4339 gtk_text_buffer_end_user_action (priv->text_buffer);
4342 static void update_branding (ModestMsgEditWindow *self,
4343 const gchar *new_account)
4345 ModestMsgEditWindowPrivate *priv;
4346 ModestAccountMgr *mgr;
4347 const GdkPixbuf *new_icon = NULL;
4348 gchar *new_label = NULL;
4349 gboolean show = FALSE;
4351 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4353 mgr = modest_runtime_get_account_mgr ();
4355 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4357 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4358 gtk_widget_show (priv->brand_icon);
4361 gtk_widget_hide (priv->brand_icon);
4364 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4365 gtk_widget_show (priv->brand_label);
4369 gtk_widget_hide (priv->brand_label);
4373 gtk_widget_show (priv->brand_container);
4375 gtk_widget_hide (priv->brand_container);
4379 from_field_changed (GtkWidget *button,
4380 ModestMsgEditWindow *self)
4382 ModestMsgEditWindowPrivate *priv;
4383 gchar *old_account, *new_account;
4385 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4387 old_account = priv->last_from_account;
4388 new_account = modest_selector_get_active_id (priv->from_field);
4391 g_warning ("%s, could not get the new account", __FUNCTION__);
4395 /* If the From is the same do nothing */
4396 if (old_account && new_account && !strcmp (old_account, new_account))
4399 priv->last_from_account = new_account;
4401 update_signature (self, old_account, new_account);
4402 update_branding (self, new_account);
4406 typedef struct _MessageSettingsHelper {
4407 ModestMsgEditWindow *window;
4408 GSList *priority_group;
4409 GSList *format_group;
4410 GtkToggleButton *current_priority;
4411 GtkToggleButton *current_format;
4412 } MessageSettingsHelper;
4415 on_priority_toggle (GtkToggleButton *button,
4416 MessageSettingsHelper *helper)
4419 ModestMsgEditWindowPrivate *priv;
4421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4422 if (gtk_toggle_button_get_active (button)) {
4424 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4425 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4426 if ((node_button != button) &&
4427 gtk_toggle_button_get_active (node_button)) {
4428 gtk_toggle_button_set_active (node_button, FALSE);
4431 helper->current_priority = button;
4433 gboolean found = FALSE;
4434 /* If no one is active, activate it again */
4435 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4436 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4437 if (gtk_toggle_button_get_active (node_button)) {
4443 gtk_toggle_button_set_active (button, TRUE);
4449 on_format_toggle (GtkToggleButton *button,
4450 MessageSettingsHelper *helper)
4453 ModestMsgEditWindowPrivate *priv;
4455 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4456 if (gtk_toggle_button_get_active (button)) {
4458 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4459 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4460 if ((node_button != button) &&
4461 gtk_toggle_button_get_active (node_button)) {
4462 gtk_toggle_button_set_active (node_button, FALSE);
4465 helper->current_format = button;
4467 gboolean found = FALSE;
4468 /* If no one is active, activate it again */
4469 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4470 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4471 if (gtk_toggle_button_get_active (node_button)) {
4477 gtk_toggle_button_set_active (button, TRUE);
4484 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4489 GtkWidget *priority_hbox;
4490 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4491 GtkWidget *captioned;
4492 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4493 GtkWidget *format_hbox;
4494 GtkWidget *html_toggle, *text_toggle;
4495 ModestMsgEditWindowPrivate *priv;
4496 MessageSettingsHelper helper = {0,};
4498 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4499 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4500 helper.window = window;
4501 helper.priority_group = NULL;
4502 helper.format_group = NULL;
4504 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4505 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4507 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4508 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4509 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4510 vbox = gtk_vbox_new (FALSE, 0);
4511 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4512 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4513 gtk_container_add (GTK_CONTAINER (align), vbox);
4514 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4515 gtk_widget_show (align);
4516 gtk_widget_show (vbox);
4518 /* Priority toggles */
4519 priority_hbox = gtk_hbox_new (TRUE, 0);
4520 #ifdef MODEST_TOOLKIT_HILDON2
4521 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4523 high_toggle = gtk_toggle_button_new ();
4525 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4526 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4527 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4528 #ifdef MODEST_TOOLKIT_HILDON2
4529 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4531 medium_toggle = gtk_toggle_button_new ();
4533 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4534 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4535 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4536 #ifdef MODEST_TOOLKIT_HILDON2
4537 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4539 low_toggle = gtk_toggle_button_new ();
4541 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4542 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4543 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4544 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4545 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4546 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4547 gtk_widget_show_all (priority_hbox);
4548 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4549 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4550 gtk_widget_show (captioned);
4551 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4553 /* format toggles */
4554 format_hbox = gtk_hbox_new (TRUE, 0);
4555 #ifdef MODEST_TOOLKIT_HILDON2
4556 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4558 html_toggle = gtk_toggle_button_new ();
4560 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4561 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4562 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4563 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4564 #ifdef MODEST_TOOLKIT_HILDON2
4565 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4567 text_toggle = gtk_toggle_button_new ();
4569 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4570 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4571 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4572 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4573 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4574 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4575 gtk_widget_show_all (format_hbox);
4576 gtk_widget_show (format_hbox);
4577 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4580 g_object_unref (title_sizegroup);
4581 g_object_unref (value_sizegroup);
4583 /* Set current values */
4584 switch (priv->priority_flags) {
4585 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4586 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4587 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4589 case TNY_HEADER_FLAG_LOW_PRIORITY:
4590 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4591 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4594 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4595 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4599 switch (modest_msg_edit_window_get_format (window)) {
4600 case MODEST_MSG_EDIT_FORMAT_TEXT:
4601 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4602 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4604 case MODEST_MSG_EDIT_FORMAT_HTML:
4606 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4607 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4611 /* Signal connects */
4612 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4613 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4614 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4615 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4616 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4618 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4619 GTK_WINDOW (dialog), GTK_WINDOW (window));
4621 /* Save settings if the user clicked on done */
4622 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4623 TnyHeaderFlags flags;
4624 ModestMsgEditFormat old_format, new_format;
4626 /* Set priority flags */
4627 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4628 if (priv->priority_flags != flags)
4629 modest_msg_edit_window_set_priority_flags (window, flags);
4631 /* Set edit format */
4632 old_format = modest_msg_edit_window_get_format (window);
4633 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4634 if (old_format != new_format) {
4635 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4636 modest_msg_edit_window_set_file_format (window, file_format);
4640 gtk_widget_destroy (dialog);
4641 g_slist_free (helper.priority_group);
4645 on_message_settings (GtkAction *action,
4646 ModestMsgEditWindow *window)
4648 modest_msg_edit_window_show_msg_settings_dialog (window);
4652 on_show_toolbar_button_toggled (GtkWidget *button,
4653 ModestMsgEditWindow *window)
4655 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4657 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4658 modest_togglable_get_active (button));
4662 on_cc_button_toggled (GtkWidget *button,
4663 ModestMsgEditWindow *window)
4665 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4667 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4668 modest_togglable_get_active (button));
4672 on_bcc_button_toggled (GtkWidget *button,
4673 ModestMsgEditWindow *window)
4675 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4677 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4678 modest_togglable_get_active (button));
4682 setup_menu (ModestMsgEditWindow *self)
4684 ModestMsgEditWindowPrivate *priv = NULL;
4686 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4688 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4690 /* Settings menu buttons */
4691 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4692 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4694 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4695 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4696 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4697 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4698 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4699 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4701 priv->cc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4702 _("mcen_me_editor_showcc"));
4703 modest_togglable_set_active (priv->cc_button,
4705 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4706 gtk_widget_show (priv->cc_button);
4707 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4708 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4710 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4711 _("mcen_me_editor_showbcc"));
4712 gtk_widget_show (priv->bcc_button);
4713 modest_togglable_set_active (priv->bcc_button,
4715 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4717 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4718 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4720 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4721 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4722 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4723 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4724 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4726 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4727 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4728 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4729 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4730 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4732 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4733 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4736 priv->show_toolbar_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4737 _("mcen_bd_show_toolbar"));
4738 modest_togglable_set_active (priv->show_toolbar_button,
4740 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->show_toolbar_button,
4741 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4742 gtk_widget_show (priv->show_toolbar_button);
4743 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4744 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4749 emit_open_addressbook (GtkButton *button,
4750 ModestRecptEditor *editor)
4752 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4756 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4757 const gchar *label, GtkWidget *control)
4759 GtkWidget *abook_button;
4762 GtkWidget *label_widget;
4764 box = gtk_hbox_new (FALSE, 0);
4766 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4767 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);
4776 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4778 gtk_container_add (GTK_CONTAINER (align), abook_button);
4779 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4780 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4781 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4782 if (title_size_group)
4783 gtk_size_group_add_widget (title_size_group, label_widget);
4784 if (value_size_group)
4785 gtk_size_group_add_widget (value_size_group, control);
4787 g_signal_connect (G_OBJECT (abook_button), "clicked",
4788 G_CALLBACK (emit_open_addressbook), control);
4794 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4796 ModestMsgEditWindowPrivate *priv = NULL;
4798 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4801 priv->max_chars_banner = NULL;
4805 has_pending_addresses (ModestRecptEditor *recpt_editor)
4807 const gchar *recipients = NULL;
4808 GSList *start_indexes = NULL, *end_indexes = NULL;
4809 GSList *current_start, *current_end;
4810 GtkTextBuffer *buffer;
4811 gint offset_delta = 0;
4813 gboolean has_recipients_to_add = FALSE;
4815 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4816 last_length = g_utf8_strlen (recipients, -1);
4817 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4822 current_start = start_indexes;
4823 current_end = end_indexes;
4824 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4826 while (current_start && !has_recipients_to_add) {
4828 gchar *start_ptr, *end_ptr;
4829 gint start_pos, end_pos;
4831 start_pos = (*((gint*) current_start->data)) + offset_delta;
4832 end_pos = (*((gint*) current_end->data)) + offset_delta;
4834 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4835 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4837 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4839 if (modest_text_utils_validate_recipient (address, NULL)) {
4840 if (!modest_address_book_has_address (address)) {
4841 has_recipients_to_add = TRUE;
4844 current_start = g_slist_next (current_start);
4845 current_end = g_slist_next (current_end);
4847 return has_recipients_to_add;
4851 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4853 ModestMsgEditWindowPrivate *priv = NULL;
4855 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4857 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4859 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4860 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4861 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))
4868 modest_msg_edit_window_set_custom_header_pairs (ModestMsgEditWindow *self,
4869 TnyList *header_pairs)
4871 ModestMsgEditWindowPrivate *priv = NULL;
4873 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
4874 g_return_if_fail (TNY_IS_LIST (header_pairs));
4876 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4877 g_object_unref (priv->custom_header_pairs);
4878 priv->custom_header_pairs = tny_list_copy (header_pairs);