1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <modest-scrollable.h>
67 #include <modest-isearch-toolbar.h>
68 #include "modest-msg-edit-window-ui-dimming.h"
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #include <libgnomevfs/gnome-vfs-mime.h>
72 #include <modest-utils.h>
73 #include <modest-ui-constants.h>
74 #include <modest-toolkit-utils.h>
76 #ifdef MODEST_USE_CALENDAR_WIDGETS
77 #include <calendar-ui-widgets.h>
79 #ifdef MODEST_TOOLKIT_HILDON2
80 #include <hildon/hildon.h>
81 #include "modest-maemo-utils.h"
82 #include "modest-hildon-includes.h"
83 #include "modest-color-button.h"
86 #define DEFAULT_MAIN_VBOX_SPACING 0
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #ifdef MODEST_TOOLKIT_HILDON2
90 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
91 #define DEFAULT_FONT_SCALE 1.5
92 #define DEFAULT_FONT_SIZE 3
93 #define DEFAULT_FONT 2
95 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
96 #define DEFAULT_FONT_SCALE 1.0
97 #define DEFAULT_FONT_SIZE 2
98 #define DEFAULT_FONT 2
100 #define ATTACHMENT_BUTTON_WIDTH 118
101 #define MAX_FROM_VALUE 36
102 #define MAX_BODY_LENGTH 128*1024
103 #define MAX_BODY_LINES 2048
105 static gboolean is_wp_text_buffer_started = FALSE;
107 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
108 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
109 static void modest_msg_edit_window_finalize (GObject *obj);
111 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
112 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
113 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
115 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
116 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
117 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
118 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
119 GtkTextIter *start, GtkTextIter *end,
121 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
122 static void body_insert_text (GtkTextBuffer *buffer,
123 GtkTextIter *location,
126 ModestMsgEditWindow *window);
127 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
128 static void subject_field_insert_text (GtkEditable *editable,
130 gint new_text_length,
132 ModestMsgEditWindow *window);
133 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
135 #ifdef MODEST_TOOLKIT_HILDON2
136 static void font_face_clicked (GtkToolButton *button,
137 ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
142 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
145 ModestRecptEditor *editor);
146 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
147 ModestMsgEditWindow *window);
149 /* ModestWindow methods implementation */
150 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
151 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
152 gboolean show_toolbar);
153 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
155 ModestMsgEditWindow *window);
156 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
157 static void subject_field_move_cursor (GtkEntry *entry,
158 GtkMovementStep step,
162 static void update_window_title (ModestMsgEditWindow *window);
165 static void modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
166 ModestMsgEditWindow *window);
167 static void modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
168 ModestMsgEditWindow *window);
169 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
171 GtkTextIter *match_start,
172 GtkTextIter *match_end);
174 static void remove_tags (WPTextBuffer *buffer);
176 static void on_account_removed (TnyAccountStore *account_store,
180 static void init_window (ModestMsgEditWindow *obj);
182 gboolean scroll_drag_timeout (gpointer userdata);
183 static void correct_scroll (ModestMsgEditWindow *w);
184 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
185 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
186 ModestMsgEditWindow *userdata);
187 static void text_buffer_mark_set (GtkTextBuffer *buffer,
190 ModestMsgEditWindow *userdata);
191 static void on_show_toolbar_button_toggled (GtkWidget *button,
192 ModestMsgEditWindow *window);
193 static void on_message_settings (GtkAction *action,
194 ModestMsgEditWindow *window);
195 static void setup_menu (ModestMsgEditWindow *self);
197 static void from_field_changed (GtkWidget *button,
198 ModestMsgEditWindow *self);
199 static void font_size_clicked (GtkToolButton *button,
200 ModestMsgEditWindow *window);
201 static void update_signature (ModestMsgEditWindow *self,
202 const gchar *old_account,
203 const gchar *new_account);
204 static void update_branding (ModestMsgEditWindow *self,
205 const gchar *new_account);
206 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
207 const gchar *label, GtkWidget *control);
208 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
209 static void DEBUG_BUFFER (WPTextBuffer *buffer)
213 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
215 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
216 while (!gtk_text_iter_is_end (&iter)) {
217 GString *output = g_string_new ("");
218 GSList *toggled_tags;
221 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
222 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
223 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
224 GtkTextTag *tag = (GtkTextTag *) node->data;
226 g_object_get (G_OBJECT (tag), "name", &name, NULL);
227 output = g_string_append (output, name);
228 g_string_append (output, " ");
230 output = g_string_append (output, "] OPENED [ ");
231 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
232 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
233 GtkTextTag *tag = (GtkTextTag *) node->data;
235 g_object_get (G_OBJECT (tag), "name", &name, NULL);
236 output = g_string_append (output, name);
237 g_string_append (output, " ");
239 output = g_string_append (output, "]\n");
240 g_debug ("%s", output->str);
241 g_string_free (output, TRUE);
242 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
244 g_debug ("END BUFFER");
248 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
249 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
253 /* static gboolean */
254 /* on_key_pressed (GtkWidget *self, */
255 /* GdkEventKey *event, */
256 /* gpointer user_data); */
258 /* list my signals */
265 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
266 struct _ModestMsgEditWindowPrivate {
268 GtkWidget *header_box;
270 ModestPairList *from_field_protos;
271 GtkWidget *from_field;
272 gchar *last_from_account;
273 gchar *original_account_name;
278 gchar *original_mailbox;
282 GtkWidget *bcc_field;
283 GtkWidget *subject_field;
284 GtkWidget *attachments_view;
285 GtkWidget *priority_icon;
286 GtkWidget *subject_box;
287 GtkWidget *send_button;
289 GtkWidget *cc_caption;
290 GtkWidget *bcc_caption;
291 gboolean update_caption_visibility;
292 GtkWidget *attachments_caption;
294 GtkTextBuffer *text_buffer;
296 GtkWidget *font_size_toolitem;
297 GtkWidget *font_face_toolitem;
298 GtkWidget *font_color_button;
299 GtkWidget *font_color_toolitem;
300 GSList *font_items_group;
301 GtkTreeModel *faces_model;
302 gint current_face_index;
303 GtkWidget *font_tool_button_label;
304 GtkTreeModel *sizes_model;
305 gint current_size_index;
306 GtkWidget *size_tool_button_label;
308 GtkWidget *isearch_toolbar;
311 GtkWidget *font_dialog;
313 GtkWidget *scrollable;
314 guint correct_scroll_idle;
315 guint scroll_drag_timeout_id;
319 TnyList *attachments;
324 TnyHeaderFlags priority_flags;
326 gboolean can_undo, can_redo;
327 gulong clipboard_change_handler_id;
328 gulong default_clipboard_change_handler_id;
329 gulong account_removed_handler_id;
330 guint clipboard_owner_idle;
331 gchar *clipboard_text;
340 GtkWidget *cc_button;
341 GtkWidget *bcc_button;
342 GtkWidget *show_toolbar_button;
344 GtkWidget *max_chars_banner;
346 GtkWidget *brand_icon;
347 GtkWidget *brand_label;
348 GtkWidget *brand_container;
350 TnyList *custom_header_pairs;
353 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
354 MODEST_TYPE_MSG_EDIT_WINDOW, \
355 ModestMsgEditWindowPrivate))
357 static ModestWindowParentClass *parent_class = NULL;
359 /* uncomment the following if you have defined any signals */
360 /* static guint signals[LAST_SIGNAL] = {0}; */
363 modest_msg_edit_window_get_type (void)
365 static GType my_type = 0;
367 static const GTypeInfo my_info = {
368 sizeof(ModestMsgEditWindowClass),
369 NULL, /* base init */
370 NULL, /* base finalize */
371 (GClassInitFunc) modest_msg_edit_window_class_init,
372 NULL, /* class finalize */
373 NULL, /* class data */
374 sizeof(ModestMsgEditWindow),
376 (GInstanceInitFunc) modest_msg_edit_window_init,
379 my_type = g_type_register_static (
380 #ifdef MODEST_TOOLKIT_HILDON2
381 MODEST_TYPE_HILDON2_WINDOW,
383 MODEST_TYPE_SHELL_WINDOW,
385 "ModestMsgEditWindow",
393 save_state (ModestWindow *self)
395 modest_widget_memory_save (modest_runtime_get_conf(),
396 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
401 restore_settings (ModestMsgEditWindow *self)
403 ModestConf *conf = NULL;
405 conf = modest_runtime_get_conf ();
407 /* Dim at start clipboard actions */
408 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
413 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
415 GObjectClass *gobject_class;
416 ModestWindowClass *modest_window_class;
417 gobject_class = (GObjectClass*) klass;
418 modest_window_class = (ModestWindowClass*) klass;
420 parent_class = g_type_class_peek_parent (klass);
421 gobject_class->finalize = modest_msg_edit_window_finalize;
423 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
424 modest_window_class->save_state_func = save_state;
425 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
427 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
431 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
433 ModestMsgEditWindowPrivate *priv;
434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
436 priv->msg_body = NULL;
437 priv->from_field = NULL;
438 priv->to_field = NULL;
439 priv->cc_field = NULL;
440 priv->bcc_field = NULL;
441 priv->subject_field = NULL;
442 priv->attachments = TNY_LIST (tny_simple_list_new ());
443 priv->images = TNY_LIST (tny_simple_list_new ());
444 priv->images_size = 0;
445 priv->images_count = 0;
448 priv->cc_caption = NULL;
449 priv->bcc_caption = NULL;
450 priv->update_caption_visibility = FALSE;
452 priv->priority_flags = 0;
454 priv->isearch_toolbar = NULL;
455 priv->last_search = NULL;
457 priv->draft_msg = NULL;
458 priv->outbox_msg = NULL;
459 priv->msg_uid = NULL;
461 priv->can_undo = FALSE;
462 priv->can_redo = FALSE;
463 priv->clipboard_change_handler_id = 0;
464 priv->default_clipboard_change_handler_id = 0;
465 priv->account_removed_handler_id = 0;
466 priv->clipboard_owner_idle = 0;
467 priv->clipboard_text = NULL;
470 priv->scroll_drag_timeout_id = 0;
471 priv->correct_scroll_idle = 0;
472 priv->last_upper = 0.0;
474 priv->font_dialog = NULL;
475 priv->app_menu = NULL;
477 priv->references = NULL;
478 priv->in_reply_to = NULL;
479 priv->max_chars_banner = NULL;
480 priv->custom_header_pairs = TNY_LIST (tny_simple_list_new ());
482 if (!is_wp_text_buffer_started) {
483 is_wp_text_buffer_started = TRUE;
484 wp_text_buffer_library_init ();
488 #ifdef MODEST_TOOLKIT_HILDON2
489 hildon_program_add_window (hildon_program_get_instance(),
495 multimailbox_get_default_mailbox (const gchar *account_name)
497 gchar *transport_account;
498 gchar *result = NULL;
500 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
502 TNY_ACCOUNT_TYPE_TRANSPORT);
503 if (transport_account) {
505 ModestProtocolRegistry *registry;
507 registry = modest_runtime_get_protocol_registry ();
509 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
510 MODEST_ACCOUNT_PROTO, TRUE);
512 ModestProtocol *protocol =
513 modest_protocol_registry_get_protocol_by_name (registry,
514 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
516 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
517 ModestPairList *pair_list;
519 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
522 ModestPair *pair = (ModestPair *) pair_list->data;
523 result = g_strdup ((const gchar *) pair->first);
524 modest_pair_list_free (pair_list);
535 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
537 static ModestPairList*
538 get_transports (void)
540 GSList *transports = NULL;
542 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
543 GSList *accounts = modest_account_mgr_account_names (account_mgr,
544 TRUE /* only enabled accounts. */);
546 GSList *cursor = accounts;
548 gchar *account_name = cursor->data;
551 gchar *transport_account;
552 gboolean multi_mailbox = FALSE;
553 ModestProtocol *protocol = NULL;
555 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
557 transport_account = modest_account_mgr_get_server_account_name
558 (modest_runtime_get_account_mgr (),
560 TNY_ACCOUNT_TYPE_TRANSPORT);
561 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
562 ModestPairList *pair_list;
563 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
566 transports = g_slist_concat (transports, pair_list);
567 multi_mailbox = TRUE;
572 if (!multi_mailbox) {
573 gchar *from_string = NULL;
575 from_string = modest_account_mgr_get_from_string (account_mgr,
577 if (from_string && account_name) {
578 gchar *name = account_name;
579 ModestPair *pair = modest_pair_new ((gpointer) name,
580 (gpointer) from_string , TRUE);
581 transports = g_slist_prepend (transports, pair);
586 cursor = cursor->next;
588 g_slist_free (accounts); /* only free the accounts, not the elements,
589 * because they are used in the pairlist */
593 static void window_focus (GtkWindow *window,
597 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
601 scroll_drag_timeout (gpointer userdata)
603 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
604 ModestMsgEditWindowPrivate *priv;
606 /* It could happen that the window was already closed */
607 if (!GTK_WIDGET_VISIBLE (win))
610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
612 correct_scroll_without_drag_check (win, TRUE);
614 priv->scroll_drag_timeout_id = 0;
620 correct_scroll_without_drag_check_idle (gpointer userdata)
622 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
623 ModestMsgEditWindowPrivate *priv;
625 GdkRectangle rectangle;
626 gint offset_min, offset_max;
630 /* It could happen that the window was already closed */
631 if (!GTK_WIDGET_VISIBLE (w))
634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
636 insert = gtk_text_buffer_get_insert (priv->text_buffer);
637 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
639 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
640 offset_min = priv->msg_body->allocation.y + rectangle.y;
641 offset_max = offset_min + rectangle.height;
643 vadj = modest_scrollable_get_vadjustment (MODEST_SCROLLABLE (priv->scrollable));
644 offset_min = MAX (offset_min - 48, 0);
645 offset_max = MIN (offset_max + 48, vadj->upper);
647 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
649 priv->correct_scroll_idle = 0;
654 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
656 ModestMsgEditWindowPrivate *priv;
658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
660 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
663 if (priv->correct_scroll_idle > 0) {
667 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
668 (GSourceFunc) correct_scroll_without_drag_check_idle,
674 correct_scroll (ModestMsgEditWindow *w)
676 ModestMsgEditWindowPrivate *priv;
678 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
679 if (gtk_grab_get_current () == priv->msg_body) {
680 if (priv->scroll_drag_timeout_id == 0) {
681 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
683 (GSourceFunc) scroll_drag_timeout,
690 correct_scroll_without_drag_check (w, TRUE);
694 text_buffer_end_user_action (GtkTextBuffer *buffer,
695 ModestMsgEditWindow *userdata)
698 correct_scroll (userdata);
702 text_buffer_mark_set (GtkTextBuffer *buffer,
705 ModestMsgEditWindow *userdata)
707 gtk_text_buffer_begin_user_action (buffer);
708 gtk_text_buffer_end_user_action (buffer);
712 cut_clipboard_check (GtkTextView *text_view,
715 GtkTextBuffer *buffer;
717 buffer = gtk_text_view_get_buffer (text_view);
718 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
719 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
724 copy_clipboard_check (GtkTextView *text_view,
727 GtkTextBuffer *buffer;
729 buffer = gtk_text_view_get_buffer (text_view);
730 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
731 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
736 attachment_deleted (ModestAttachmentsView *attachments_view,
739 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
744 body_size_request (GtkWidget *body,
748 /* Make sure the body always get at least 70 pixels */
749 if (req->height < 70)
754 connect_signals (ModestMsgEditWindow *obj)
756 ModestMsgEditWindowPrivate *priv;
758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
760 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
761 G_CALLBACK (text_buffer_refresh_attributes), obj);
762 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
763 G_CALLBACK (text_buffer_can_undo), obj);
764 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
765 G_CALLBACK (text_buffer_can_redo), obj);
766 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
767 G_CALLBACK (body_changed), obj);
768 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
769 G_CALLBACK (body_insert_text), obj);
770 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
771 G_CALLBACK (body_changed), obj);
772 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
773 G_CALLBACK (text_buffer_end_user_action), obj);
774 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
775 G_CALLBACK (text_buffer_mark_set), obj);
776 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
777 G_CALLBACK (text_buffer_apply_tag), obj);
778 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
779 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
780 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
781 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
782 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
783 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
785 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
786 G_CALLBACK (modest_ui_actions_on_send), obj);
788 if (GTK_IS_COMBO_BOX (priv->from_field)) {
789 g_signal_connect (G_OBJECT (priv->from_field), "changed",
790 G_CALLBACK (from_field_changed), obj);
792 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
793 G_CALLBACK (from_field_changed), obj);
796 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
797 G_CALLBACK (msg_body_focus), obj);
798 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
799 G_CALLBACK (msg_body_focus), obj);
800 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
801 G_CALLBACK (body_size_request), obj);
802 if (GTK_IS_WINDOW (obj)) {
803 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
805 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
806 "changed", G_CALLBACK (recpt_field_changed), obj);
807 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
808 "changed", G_CALLBACK (recpt_field_changed), obj);
809 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
810 "changed", G_CALLBACK (recpt_field_changed), obj);
811 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
812 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
813 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
815 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-search",
816 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_search), obj);
817 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-close",
818 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_close), obj);
820 priv->clipboard_change_handler_id =
821 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
822 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
823 priv->default_clipboard_change_handler_id =
824 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
825 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
827 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
828 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
829 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
833 init_wp_text_view_style ()
835 static gboolean initialized = FALSE;
838 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
844 init_window (ModestMsgEditWindow *obj)
846 GtkWidget *to_caption, *subject_caption;
847 GtkWidget *main_vbox;
848 ModestMsgEditWindowPrivate *priv;
849 GtkActionGroup *action_group;
850 ModestWindowPrivate *parent_priv;
851 GError *error = NULL;
853 GtkSizeGroup *title_size_group;
854 GtkSizeGroup *value_size_group;
855 GtkWidget *window_box;
856 GtkWidget *window_align;
857 #if (GTK_MINOR_VERSION >= 10)
858 GdkAtom deserialize_type;
860 GtkWidget *from_send_hbox;
861 GtkWidget *send_icon;
862 GtkWidget *attachments_label;
863 GtkWidget *branding_box;
864 GtkWidget *from_caption;
866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
867 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
869 parent_priv->ui_manager = gtk_ui_manager_new();
870 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
871 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
873 /* Add common actions */
874 gtk_action_group_add_actions (action_group,
875 modest_msg_edit_action_entries,
876 G_N_ELEMENTS (modest_msg_edit_action_entries),
878 gtk_action_group_add_actions (action_group,
879 hildon2_msg_edit_action_entries,
880 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
882 gtk_action_group_add_toggle_actions (action_group,
883 modest_msg_edit_toggle_action_entries,
884 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
886 gtk_action_group_add_radio_actions (action_group,
887 modest_msg_edit_alignment_radio_action_entries,
888 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
890 G_CALLBACK (modest_ui_actions_on_change_justify),
892 gtk_action_group_add_radio_actions (action_group,
893 modest_msg_edit_priority_action_entries,
894 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
896 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
898 gtk_action_group_add_radio_actions (action_group,
899 modest_msg_edit_file_format_action_entries,
900 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
901 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
902 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
904 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
905 g_object_unref (action_group);
907 /* Load the UI definition */
908 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
911 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
912 g_clear_error (&error);
915 parent_priv->menubar = NULL;
917 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
918 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
920 /* Note: This ModestPairList* must exist for as long as the picker
921 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
922 * so it can't know how to manage its memory. */
923 priv->from_field = modest_toolkit_factory_create_selector (modest_runtime_get_toolkit_factory (),
924 NULL, g_str_equal, FALSE);
925 modest_selector_set_value_max_chars (priv->from_field, MAX_FROM_VALUE);
926 if (GTK_IS_COMBO_BOX (priv->from_field)) {
927 from_caption = modest_toolkit_utils_create_captioned (title_size_group, NULL,
928 _("mail_va_from"), FALSE,
930 gtk_widget_show (from_caption);
932 #ifdef MODEST_TOOLKIT_HILDON2
933 modest_toolkit_utils_set_hbutton_layout (title_size_group, NULL,
934 _("mail_va_from"), priv->from_field);
935 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
936 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
937 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
938 from_caption = priv->from_field;
942 priv->to_field = modest_recpt_editor_new ();
943 priv->cc_field = modest_recpt_editor_new ();
944 priv->bcc_field = modest_recpt_editor_new ();
945 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
946 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
947 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
948 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
949 priv->priority_icon = gtk_image_new ();
950 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
951 priv->subject_field = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
952 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
953 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
954 modest_entry_set_hint (priv->subject_field, _("mail_va_no_subject"));
956 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
957 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
959 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
960 priv->attachments_view = modest_attachments_view_new (NULL);
961 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
962 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
964 priv->header_box = gtk_vbox_new (FALSE, 0);
966 to_caption = _create_addressbook_box
967 (title_size_group, value_size_group,
968 _("mail_va_to"), priv->to_field);
969 priv->cc_caption = _create_addressbook_box
970 (title_size_group, value_size_group,
971 _("mail_va_cc"), priv->cc_field);
972 priv->bcc_caption = _create_addressbook_box
973 (title_size_group, value_size_group,
974 _("mail_va_hotfix1"), priv->bcc_field);
975 subject_caption = modest_toolkit_utils_create_captioned (title_size_group, value_size_group,
976 _("mail_va_subject"), FALSE, priv->subject_box);
977 priv->attachments_caption = modest_toolkit_utils_create_captioned_with_size_type (NULL, NULL,
978 _("mail_va_attachment"),
980 priv->attachments_view,
981 #ifdef MODEST_TOOLKIT_HILDON2
982 HILDON_SIZE_AUTO_WIDTH |
983 HILDON_SIZE_AUTO_HEIGHT
988 attachments_label = modest_toolkit_utils_captioned_get_label_widget (priv->attachments_caption);
990 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
994 #ifdef MODEST_TOOLKIT_HILDON2
995 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
996 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
998 priv->send_button = gtk_button_new ();
999 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, GTK_ICON_SIZE_BUTTON);
1001 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
1002 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
1004 g_object_unref (title_size_group);
1005 g_object_unref (value_size_group);
1007 priv->brand_icon = gtk_image_new ();
1008 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
1009 priv->brand_label = gtk_label_new (NULL);
1010 #ifdef MODEST_TOOLKIT_HILDON2
1011 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
1013 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
1014 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
1015 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
1017 from_send_hbox = gtk_hbox_new (FALSE, 0);
1018 gtk_box_pack_start (GTK_BOX (from_send_hbox), from_caption, TRUE, TRUE, 0);
1019 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1021 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1022 gtk_widget_show (branding_box);
1023 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1024 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1026 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1027 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1028 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1029 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1032 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1033 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1034 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1035 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1036 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1037 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1038 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1039 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1041 init_wp_text_view_style ();
1043 priv->msg_body = modest_wp_text_view_new ();
1046 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1047 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1048 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1049 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1050 #if (GTK_MINOR_VERSION >= 10)
1051 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1052 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1054 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1055 deserialize_type, TRUE);
1057 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1059 priv->isearch_toolbar = modest_toolkit_factory_create_isearch_toolbar (modest_runtime_get_toolkit_factory (),
1061 gtk_widget_set_no_show_all (priv->isearch_toolbar, TRUE);
1063 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1065 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1067 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1068 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1069 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), MODEST_MARGIN_HALF, 0,
1070 MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1072 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1073 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1074 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1076 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1077 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1079 window_box = gtk_vbox_new (FALSE, 0);
1080 gtk_container_add (GTK_CONTAINER(obj), window_box);
1082 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1087 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1089 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1091 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1092 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1093 priv->clipboard_change_handler_id))
1094 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1095 priv->clipboard_change_handler_id);
1096 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1097 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1098 priv->default_clipboard_change_handler_id))
1099 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1100 priv->default_clipboard_change_handler_id);
1102 if (priv->account_removed_handler_id &&
1103 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1104 priv->account_removed_handler_id))
1105 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1106 priv->account_removed_handler_id);
1110 modest_msg_edit_window_finalize (GObject *obj)
1112 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1114 g_object_unref (priv->custom_header_pairs);
1116 if (priv->max_chars_banner) {
1117 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1118 priv->max_chars_banner = FALSE;
1121 /* Sanity check: shouldn't be needed, the window mgr should
1122 call this function before */
1123 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1125 if (priv->font_dialog != NULL) {
1126 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1129 if (priv->clipboard_text != NULL) {
1130 g_free (priv->clipboard_text);
1131 priv->clipboard_text = NULL;
1134 if (priv->draft_msg != NULL) {
1135 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1136 if (TNY_IS_HEADER (header)) {
1137 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1138 modest_window_mgr_unregister_header (mgr, header);
1140 g_object_unref (priv->draft_msg);
1141 priv->draft_msg = NULL;
1143 if (priv->outbox_msg != NULL) {
1144 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1145 if (TNY_IS_HEADER (header)) {
1146 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1147 modest_window_mgr_unregister_header (mgr, header);
1149 g_object_unref (priv->outbox_msg);
1150 priv->outbox_msg = NULL;
1152 if (priv->correct_scroll_idle > 0) {
1153 g_source_remove (priv->correct_scroll_idle);
1154 priv->correct_scroll_idle = 0;
1156 if (priv->scroll_drag_timeout_id > 0) {
1157 g_source_remove (priv->scroll_drag_timeout_id);
1158 priv->scroll_drag_timeout_id = 0;
1160 if (priv->clipboard_owner_idle > 0) {
1161 g_source_remove (priv->clipboard_owner_idle);
1162 priv->clipboard_owner_idle = 0;
1164 if (priv->original_account_name)
1165 g_free (priv->original_account_name);
1166 if (priv->original_mailbox)
1167 g_free (priv->original_mailbox);
1168 g_free (priv->msg_uid);
1169 g_free (priv->last_search);
1170 g_slist_free (priv->font_items_group);
1171 g_free (priv->references);
1172 g_free (priv->in_reply_to);
1173 g_object_unref (priv->attachments);
1174 g_object_unref (priv->images);
1176 /* This had to stay alive for as long as the picker that used it: */
1177 modest_pair_list_free (priv->from_field_protos);
1179 G_OBJECT_CLASS(parent_class)->finalize (obj);
1183 pixbuf_size_prepared (GdkPixbufLoader *loader,
1186 ModestMsgEditWindow *self)
1188 gint new_height, new_width;
1191 new_height = height;
1195 if (width > IMAGE_MAX_WIDTH) {
1196 new_height = height * IMAGE_MAX_WIDTH / width;
1197 new_width = IMAGE_MAX_WIDTH;
1200 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1204 pixbuf_from_stream (TnyStream *stream,
1205 const gchar *mime_type,
1206 guint64 *stream_size,
1207 ModestMsgEditWindow *self)
1209 GdkPixbufLoader *loader;
1212 GError *error = NULL;
1216 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1218 if (loader == NULL) {
1223 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1225 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1227 tny_stream_reset (TNY_STREAM (stream));
1228 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1229 unsigned char read_buffer[128];
1231 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1233 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1236 /* Allow some UI responsiveness */
1237 while (gtk_events_pending ())
1238 gtk_main_iteration ();
1240 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1242 gdk_pixbuf_loader_close (loader, &error);
1245 g_error_free (error);
1246 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1248 g_object_ref (pixbuf);
1249 g_object_unref (loader);
1254 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1255 GdkPixbuf *new_pixbuf;
1257 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1258 gdk_pixbuf_get_width (pixbuf);
1259 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1260 g_object_unref (pixbuf);
1261 pixbuf = new_pixbuf;
1265 *stream_size = size;
1271 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1273 ModestMsgEditWindowPrivate *priv;
1276 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1278 g_object_ref (self);
1279 for (iter = tny_list_create_iterator (attachments);
1280 !tny_iterator_is_done (iter);
1281 tny_iterator_next (iter)) {
1282 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1283 const gchar *cid = tny_mime_part_get_content_id (part);
1284 const gchar *mime_type = tny_mime_part_get_content_type (part);
1285 if ((cid != NULL)&&(mime_type != NULL)) {
1286 guint64 stream_size;
1287 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1288 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1291 g_object_unref (stream);
1293 if (pixbuf != NULL) {
1294 priv->images_count ++;
1295 priv->images_size += stream_size;
1296 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1297 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1299 g_object_unref (pixbuf);
1302 g_object_unref (part);
1304 g_object_unref (iter);
1305 g_object_unref (self);
1309 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1311 TnyMimePart *parent = NULL;
1312 const gchar *content_type = NULL;
1313 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1315 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1317 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1318 parent = g_object_ref (msg);
1319 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1320 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1323 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1324 iter = tny_list_create_iterator (parts);
1325 while (!tny_iterator_is_done (iter)) {
1327 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1328 content_type = tny_mime_part_get_content_type (part);
1329 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1333 g_object_unref (part);
1335 tny_iterator_next (iter);
1337 g_object_unref (iter);
1338 g_object_unref (parts);
1341 if (parent != NULL) {
1342 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1345 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1346 iter = tny_list_create_iterator (parts);
1347 while (!tny_iterator_is_done (iter)) {
1349 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1350 content_type = tny_mime_part_get_content_type (part);
1351 if (content_type && g_str_has_prefix (content_type, "image/")) {
1352 tny_list_prepend (priv->images, (GObject *) part);
1354 g_object_unref (part);
1355 tny_iterator_next (iter);
1357 g_object_unref (iter);
1358 g_object_unref (parts);
1359 g_object_unref (parent);
1364 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1367 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1369 for (iter = tny_list_create_iterator (attachments) ;
1370 !tny_iterator_is_done (iter);
1371 tny_iterator_next (iter)) {
1372 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1373 const gchar *cid = tny_mime_part_get_content_id (part);
1375 char *invalid = NULL;
1376 gint int_cid = strtol (cid, &invalid, 10);
1377 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1378 priv->next_cid = int_cid + 1;
1381 g_object_unref (part);
1383 g_object_unref (iter);
1387 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1390 gchar *to, *cc, *bcc, *subject;
1392 ModestMsgEditWindowPrivate *priv;
1393 ModestWindowPrivate *parent_priv;
1395 TnyHeaderFlags priority_flags;
1396 TnyFolder *msg_folder;
1397 gboolean is_html = FALSE;
1398 gboolean field_view_set;
1399 TnyList *orig_header_pairs;
1401 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1402 g_return_if_fail (TNY_IS_MSG (msg));
1404 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1405 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1407 header = tny_msg_get_header (msg);
1408 to = tny_header_dup_to (header);
1409 cc = tny_header_dup_cc (header);
1410 bcc = tny_header_dup_bcc (header);
1411 subject = tny_header_dup_subject (header);
1413 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1414 priority_flags = tny_header_get_priority (header);
1417 gchar *quoted_names = modest_text_utils_quote_names (to);
1418 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1419 g_free (quoted_names);
1422 field_view_set = TRUE;
1424 gchar *quoted_names = modest_text_utils_quote_names (cc);
1425 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1426 g_free (quoted_names);
1427 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1428 gtk_widget_show (priv->cc_caption);
1429 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1430 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1431 gtk_widget_hide (priv->cc_caption);
1432 field_view_set = FALSE;
1434 modest_togglable_set_active (priv->cc_button, field_view_set);
1436 field_view_set = TRUE;
1438 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1439 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1440 g_free (quoted_names);
1441 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1442 gtk_widget_show (priv->bcc_caption);
1443 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1444 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1445 gtk_widget_hide (priv->bcc_caption);
1446 field_view_set = FALSE;
1448 modest_togglable_set_active (priv->bcc_button, field_view_set);
1452 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1453 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1456 update_window_title (self);
1458 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1459 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1461 if ((body == NULL)||(body[0] == '\0')) {
1463 body = modest_text_utils_convert_to_html ("");
1466 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1467 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1470 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1473 /* Add attachments to the view */
1474 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1475 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1476 if (tny_list_get_length (priv->attachments) == 0) {
1477 gtk_widget_hide (priv->attachments_caption);
1479 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1480 gtk_widget_show_all (priv->attachments_caption);
1482 get_related_images (self, msg);
1483 update_next_cid (self, priv->attachments);
1484 update_next_cid (self, priv->images);
1485 replace_with_images (self, priv->images);
1487 if (preserve_is_rich && !is_html) {
1488 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1489 /* Get the default format required from configuration */
1490 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1491 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1494 /* Set the default focus depending on having already a To: field or not */
1495 if ((!to)||(*to == '\0')) {
1496 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1498 gtk_widget_grab_focus (priv->msg_body);
1501 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1503 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1504 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1506 modest_msg_edit_window_set_modified (self, FALSE);
1508 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1509 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1510 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1511 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1513 if (priv->msg_uid) {
1514 g_free (priv->msg_uid);
1515 priv->msg_uid = NULL;
1518 /* we should set a reference to the incoming message if it is a draft */
1519 msg_folder = tny_msg_get_folder (msg);
1521 if (modest_tny_folder_is_local_folder (msg_folder)) {
1522 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1523 if (type == TNY_FOLDER_TYPE_INVALID)
1524 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1526 if (type == TNY_FOLDER_TYPE_DRAFTS)
1527 priv->draft_msg = g_object_ref(msg);
1528 if (type == TNY_FOLDER_TYPE_OUTBOX)
1529 priv->outbox_msg = g_object_ref(msg);
1530 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1532 g_object_unref (msg_folder);
1535 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1536 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1537 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1538 g_object_unref (orig_header_pairs);
1546 #ifndef MODEST_TOOLKIT_HILDON2
1548 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1551 GList *item_children, *node;
1552 GtkWidget *bin_child;
1554 bin_child = gtk_bin_get_child (GTK_BIN(item));
1556 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1558 for (node = item_children; node != NULL; node = g_list_next (node)) {
1559 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1560 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1563 g_list_free (item_children);
1567 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1570 GList *item_children, *node;
1572 box = gtk_bin_get_child (GTK_BIN (item));
1573 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1574 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1576 for (node = item_children; node != NULL; node = g_list_next (node)) {
1577 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1578 if (GTK_IS_TOGGLE_BUTTON (node->data))
1579 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1580 else if (GTK_IS_BUTTON (node->data))
1581 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1583 g_list_free (item_children);
1588 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1590 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1591 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1592 GtkWidget *placeholder;
1593 GtkWidget *tool_item;
1598 GtkWidget *sizes_menu;
1602 #ifndef MODEST_TOOLKIT_HILDON2
1603 GSList *radio_group, *node;
1604 GtkWidget *fonts_menu;
1608 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1609 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1610 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1611 #ifdef MODEST_TOOLKIT_HILDON2
1612 HILDON_ICON_SIZE_FINGER
1614 GTK_ICON_SIZE_LARGE_TOOLBAR
1617 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1619 /* Font color placeholder */
1620 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1621 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1624 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1625 #ifdef MODEST_TOOLKIT_HILDON2
1626 priv->font_color_button = modest_color_button_new ();
1628 priv->font_color_button = gtk_color_button_new ();
1630 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1631 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1632 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1633 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1634 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1635 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1636 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1637 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1639 G_CALLBACK (modest_msg_edit_window_color_button_change),
1642 /* Font size and face placeholder */
1643 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1644 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1646 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1647 priv->size_tool_button_label = gtk_label_new (NULL);
1648 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1649 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1650 size_text, "</span>", NULL);
1651 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1652 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1654 #ifdef MODEST_TOOLKIT_HILDON2
1655 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1657 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1658 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1659 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1660 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1661 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1662 gtk_widget_set_sensitive (arrow, FALSE);
1663 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1664 sizes_menu = gtk_menu_new ();
1665 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1666 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1669 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1670 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1672 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1676 if (wp_font_size[size_index] == 12)
1677 priv->current_size_index = size_index;
1681 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1682 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1683 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1684 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1685 priv->font_size_toolitem = tool_item;
1687 #ifdef MODEST_TOOLKIT_HILDON2
1689 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1690 priv->font_tool_button_label = gtk_label_new (NULL);
1691 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1692 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1693 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1695 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1696 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1697 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1698 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1699 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1700 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1701 gtk_widget_set_sensitive (arrow, FALSE);
1702 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1704 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1705 priv->font_tool_button_label = gtk_label_new (NULL);
1706 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1707 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1709 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1710 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1711 gtk_widget_show (priv->font_tool_button_label);
1712 gtk_widget_show (GTK_WIDGET (tool_item));
1713 fonts_menu = gtk_menu_new ();
1716 #ifdef MODEST_TOOLKIT_HILDON2
1717 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1718 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1721 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1723 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1724 0, wp_get_font_name (font_index),
1727 if (font_index == DEFAULT_FONT)
1728 priv->current_face_index = font_index;
1730 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1731 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1732 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1733 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1734 priv->font_face_toolitem = tool_item;
1736 priv->font_items_group = NULL;
1738 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1739 GtkWidget *font_menu_item;
1740 GtkWidget *child_label;
1742 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1743 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1744 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1745 wp_get_font_name (font_index), "</span>", NULL);
1746 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1749 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1750 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1751 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1752 gtk_widget_show (font_menu_item);
1754 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1757 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1758 GtkWidget *item = (GtkWidget *) node->data;
1759 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1762 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1763 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1764 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1765 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1766 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1767 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1768 priv->font_face_toolitem = tool_item;
1771 /* Set expand and homogeneous for remaining items */
1772 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1773 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1774 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1775 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1776 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1777 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1778 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1779 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1780 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1782 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1783 will not show the tool items added to the placeholders) */
1784 gtk_widget_show_all (parent_priv->toolbar);
1786 /* Set the no show all *after* showing all items. We do not
1787 want the toolbar to be shown with a show all because it
1788 could go against the gconf setting regarding showing or not
1789 the toolbar of the editor window */
1790 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1796 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1799 ModestWindowPrivate *parent_priv;
1800 ModestMsgEditWindowPrivate *priv;
1801 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1802 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1803 ModestWindowMgr *mgr = NULL;
1805 g_return_val_if_fail (msg, NULL);
1806 g_return_val_if_fail (account_name, NULL);
1808 mgr = modest_runtime_get_window_mgr ();
1810 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1813 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1815 /* Menubar. Update the state of some toggles */
1816 priv->from_field_protos = get_transports ();
1817 priv->original_mailbox = NULL;
1818 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1819 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1820 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1821 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1822 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1823 priv->original_mailbox = g_strdup (mailbox);
1824 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1825 /* We set the first mailbox as the active mailbox */
1826 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1827 if (priv->original_mailbox != NULL)
1828 modest_selector_set_active_id (priv->from_field,
1829 (gpointer) priv->original_mailbox);
1831 modest_selector_set_active_id (priv->from_field,
1832 (gpointer) account_name);
1834 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1836 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1837 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1838 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1839 #ifdef HILDON_TOOLKIT_HILDON2
1840 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1842 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1843 hildon_touch_selector_get_current_text
1844 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1847 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1848 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1851 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1853 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1855 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1856 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1858 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1860 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1861 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1862 /* Add common dimming rules */
1863 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1864 modest_msg_edit_window_toolbar_dimming_entries,
1865 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1866 MODEST_WINDOW (obj));
1867 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1868 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1869 MODEST_WINDOW (obj));
1870 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1871 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1872 MODEST_WINDOW (obj));
1873 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1874 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1875 MODEST_WINDOW (obj));
1876 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1877 G_CALLBACK (modest_ui_dimming_rules_on_send),
1878 MODEST_WINDOW (obj));
1879 /* Insert dimming rules group for this window */
1880 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1881 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1883 /* Setup app menu */
1884 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1886 /* Checks the dimming rules */
1887 g_object_unref (toolbar_rules_group);
1888 g_object_unref (clipboard_rules_group);
1889 gtk_widget_hide (priv->priority_icon);
1890 gtk_widget_queue_resize (priv->subject_box);
1891 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1893 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1895 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1896 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1897 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1898 priv->update_caption_visibility = TRUE;
1900 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1902 /* Track account-removed signal, this window should be closed
1903 in the case we're creating a mail associated to the account
1905 priv->account_removed_handler_id =
1906 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1908 G_CALLBACK(on_account_removed),
1911 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1913 return (ModestWindow*) obj;
1917 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1919 GString **string_buffer = (GString **) user_data;
1921 *string_buffer = g_string_append (*string_buffer, buffer);
1927 * @result: A new string which should be freed with g_free().
1930 get_formatted_data (ModestMsgEditWindow *edit_window)
1932 ModestMsgEditWindowPrivate *priv;
1933 GString *string_buffer = g_string_new ("");
1935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1937 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1939 modest_text_utils_hyperlinkify (string_buffer);
1941 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1943 return g_string_free (string_buffer, FALSE);
1948 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1951 const gchar *account_name;
1952 ModestMsgEditWindowPrivate *priv;
1953 TnyIterator *att_iter;
1954 const gchar *picker_active_id;
1956 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1960 picker_active_id = modest_selector_get_active_id (priv->from_field);
1961 g_return_val_if_fail (picker_active_id, NULL);
1962 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1964 /* don't free these (except from) */
1965 data = g_slice_new0 (MsgData);
1966 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1967 data->account_name = g_strdup (account_name);
1968 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1969 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1970 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1971 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1972 data->references = g_strdup (priv->references);
1973 data->in_reply_to = g_strdup (priv->in_reply_to);
1974 if (priv->draft_msg) {
1975 data->draft_msg = g_object_ref (priv->draft_msg);
1976 } else if (priv->outbox_msg) {
1977 data->draft_msg = g_object_ref (priv->outbox_msg);
1979 data->draft_msg = NULL;
1982 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1984 gtk_text_buffer_get_bounds (buf, &b, &e);
1985 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1987 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1988 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1990 data->html_body = NULL;
1992 /* deep-copy the data */
1993 att_iter = tny_list_create_iterator (priv->attachments);
1994 data->attachments = NULL;
1995 while (!tny_iterator_is_done (att_iter)) {
1996 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1997 if (!(TNY_IS_MIME_PART(part))) {
1998 g_warning ("strange data in attachment list");
1999 g_object_unref (part);
2000 tny_iterator_next (att_iter);
2003 data->attachments = g_list_append (data->attachments,
2005 tny_iterator_next (att_iter);
2007 g_object_unref (att_iter);
2009 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
2010 att_iter = tny_list_create_iterator (priv->images);
2011 data->images = NULL;
2012 while (!tny_iterator_is_done (att_iter)) {
2013 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2015 if (!(TNY_IS_MIME_PART(part))) {
2016 g_warning ("strange data in attachment list");
2017 g_object_unref (part);
2018 tny_iterator_next (att_iter);
2021 cid = tny_mime_part_get_content_id (part);
2023 gchar *image_tag_id;
2024 GtkTextTag *image_tag;
2026 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2027 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2028 g_free (image_tag_id);
2030 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2032 ((gtk_text_iter_has_tag (&iter, image_tag))||
2033 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2034 data->images = g_list_append (data->images,
2035 g_object_ref (part));
2037 g_object_unref (part);
2038 tny_iterator_next (att_iter);
2040 g_object_unref (att_iter);
2042 data->priority_flags = priv->priority_flags;
2043 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
2050 unref_gobject (GObject *obj, gpointer data)
2052 if (!G_IS_OBJECT(obj))
2054 g_object_unref (obj);
2058 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2061 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2069 g_free (data->from);
2070 g_free (data->subject);
2071 g_free (data->plain_body);
2072 g_free (data->html_body);
2073 g_free (data->account_name);
2074 g_free (data->references);
2075 g_free (data->in_reply_to);
2077 g_object_unref (data->custom_header_pairs);
2079 if (data->draft_msg != NULL) {
2080 g_object_unref (data->draft_msg);
2081 data->draft_msg = NULL;
2084 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2085 g_list_free (data->attachments);
2086 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2087 g_list_free (data->images);
2089 g_slice_free (MsgData, data);
2093 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2095 guint64 *parts_size)
2097 ModestMsgEditWindowPrivate *priv;
2099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2101 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2103 /* TODO: add images */
2104 *parts_size += priv->images_size;
2105 *parts_count += priv->images_count;
2110 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2113 ModestMsgEditWindowPrivate *priv = NULL;
2114 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2116 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2118 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2120 return MODEST_MSG_EDIT_FORMAT_HTML;
2122 return MODEST_MSG_EDIT_FORMAT_TEXT;
2126 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2127 ModestMsgEditFormat format)
2129 ModestMsgEditWindowPrivate *priv;
2130 ModestWindowPrivate *parent_priv;
2132 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2133 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2134 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2137 case MODEST_MSG_EDIT_FORMAT_HTML:
2138 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2139 update_signature (self, priv->last_from_account, priv->last_from_account);
2140 if (parent_priv->toolbar)
2141 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2142 MODEST_MSG_EDIT_WINDOW (self));
2144 case MODEST_MSG_EDIT_FORMAT_TEXT:
2145 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2146 if (parent_priv->toolbar)
2147 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2148 MODEST_MSG_EDIT_WINDOW (self));
2151 g_return_if_reached ();
2155 ModestMsgEditFormatState *
2156 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2158 ModestMsgEditFormatState *format_state = NULL;
2159 ModestMsgEditWindowPrivate *priv;
2160 WPTextBufferFormat *buffer_format;
2162 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2164 buffer_format = g_new0 (WPTextBufferFormat, 1);
2165 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2167 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2169 format_state = g_new0 (ModestMsgEditFormatState, 1);
2170 format_state->bold = buffer_format->bold&0x1;
2171 format_state->italics = buffer_format->italic&0x1;
2172 format_state->bullet = buffer_format->bullet&0x1;
2173 format_state->color = buffer_format->color;
2174 format_state->font_size = buffer_format->font_size;
2175 format_state->font_family = wp_get_font_name (buffer_format->font);
2176 format_state->justification = buffer_format->justification;
2177 g_free (buffer_format);
2179 return format_state;
2184 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2185 const ModestMsgEditFormatState *format_state)
2187 ModestMsgEditWindowPrivate *priv;
2188 WPTextBufferFormat *buffer_format;
2189 WPTextBufferFormat *current_format;
2191 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2192 g_return_if_fail (format_state != NULL);
2194 buffer_format = g_new0 (WPTextBufferFormat, 1);
2195 current_format = g_new0 (WPTextBufferFormat, 1);
2197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2198 gtk_widget_grab_focus (priv->msg_body);
2199 buffer_format->bold = (format_state->bold != FALSE);
2200 buffer_format->italic = (format_state->italics != FALSE);
2201 buffer_format->color = format_state->color;
2202 buffer_format->font_size = format_state->font_size;
2203 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2204 buffer_format->justification = format_state->justification;
2205 buffer_format->bullet = format_state->bullet;
2207 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2209 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2210 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2211 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2212 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2213 buffer_format->cs.font = (buffer_format->font != current_format->font);
2214 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2215 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2217 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2218 if (buffer_format->cs.bold) {
2219 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2220 GINT_TO_POINTER (buffer_format->bold&0x1));
2222 if (buffer_format->cs.italic) {
2223 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2224 GINT_TO_POINTER (buffer_format->italic&0x1));
2226 if (buffer_format->cs.color) {
2227 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2228 GINT_TO_POINTER (&(buffer_format->color)));
2230 if (buffer_format->cs.font_size) {
2231 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2232 GINT_TO_POINTER (buffer_format->font_size));
2234 if (buffer_format->cs.justification) {
2235 switch (buffer_format->justification) {
2236 case GTK_JUSTIFY_LEFT:
2237 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2238 GINT_TO_POINTER(TRUE));
2240 case GTK_JUSTIFY_CENTER:
2241 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2242 GINT_TO_POINTER(TRUE));
2244 case GTK_JUSTIFY_RIGHT:
2245 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2246 GINT_TO_POINTER(TRUE));
2253 if (buffer_format->cs.font) {
2254 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2255 GINT_TO_POINTER (buffer_format->font));
2257 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2258 if (buffer_format->cs.bullet) {
2259 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2260 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2262 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2264 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2266 g_free (buffer_format);
2267 g_free (current_format);
2269 /* Check dimming rules */
2270 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2271 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2275 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2277 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2279 ModestWindowPrivate *parent_priv;
2280 ModestMsgEditWindowPrivate *priv;
2282 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2283 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2285 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2286 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2287 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2288 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2290 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2291 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2292 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2295 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2297 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2298 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2300 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2301 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2303 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2304 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2307 switch (buffer_format->justification)
2309 case GTK_JUSTIFY_LEFT:
2310 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2312 case GTK_JUSTIFY_CENTER:
2313 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2315 case GTK_JUSTIFY_RIGHT:
2316 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2323 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2325 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2326 G_CALLBACK (modest_msg_edit_window_color_button_change),
2328 #ifdef MODEST_TOOLKIT_HILDON2
2329 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2331 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2333 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2334 G_CALLBACK (modest_msg_edit_window_color_button_change),
2337 if (priv->current_size_index != buffer_format->font_size) {
2341 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2342 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2346 priv->current_size_index = buffer_format->font_size;
2348 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2349 markup = g_strconcat ("<span font_family='Sans'>",
2350 size_text, "</span>", NULL);
2352 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2356 gtk_tree_path_free (path);
2359 #ifdef MODEST_TOOLKIT_HILDON2
2360 if (priv->current_face_index != buffer_format->font) {
2364 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2365 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2369 priv->current_face_index = buffer_format->font;
2370 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2371 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2372 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2379 GtkWidget *new_font_menuitem;
2380 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2381 buffer_format->font))->data);
2382 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2386 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2387 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2388 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2390 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2391 G_CALLBACK (modest_msg_edit_window_font_change),
2393 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2394 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2395 G_CALLBACK (modest_msg_edit_window_font_change),
2400 g_free (buffer_format);
2406 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2408 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2409 ModestMsgEditWindowPrivate *priv;
2410 GtkWidget *dialog = NULL;
2412 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2413 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2415 #ifdef MODEST_TOOLKIT_HILDON2
2416 dialog = hildon_color_chooser_new ();
2417 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2418 g_free (buffer_format);
2420 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2422 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2423 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2426 gtk_widget_destroy (dialog);
2428 dialog = gtk_color_selection_dialog_new (NULL);
2429 GtkWidget *selection;
2431 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2432 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2433 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2434 g_free (buffer_format);
2436 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2438 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2439 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2442 gtk_widget_destroy (dialog);
2449 create_stream_for_uri (const gchar* uri)
2454 TnyStream *result = NULL;
2456 GnomeVFSHandle *handle = NULL;
2457 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2458 if (test == GNOME_VFS_OK) {
2459 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2460 /* Streams over OBEX (Bluetooth) are not seekable but
2461 * we expect them to be (we might need to read them
2462 * several times). So if this is a Bluetooth URI just
2463 * read the whole file into memory (this is not a fast
2464 * protocol so we can assume that these files are not
2465 * going to be very big) */
2466 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2467 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2468 TnyStream *memstream = tny_camel_mem_stream_new ();
2469 tny_stream_write_to_stream (vfssstream, memstream);
2470 g_object_unref (vfssstream);
2473 result = vfssstream;
2481 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2484 ModestMsgEditWindowPrivate *priv;
2485 GtkWidget *dialog = NULL;
2487 GSList *uris = NULL;
2488 GSList *uri_node = NULL;
2490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2492 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2493 _("mcen_ia_select_inline_image_title"),
2494 (GtkWindow *) window,
2495 GTK_FILE_CHOOSER_ACTION_OPEN);
2496 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2498 #ifdef MODEST_TOOLKIT_HILDON2
2499 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2502 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2503 GTK_WINDOW (dialog), GTK_WINDOW (window));
2505 response = gtk_dialog_run (GTK_DIALOG (dialog));
2507 case GTK_RESPONSE_OK:
2509 gchar *current_folder;
2510 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2511 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2512 if (current_folder && current_folder != '\0') {
2514 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2515 current_folder, &err);
2517 g_debug ("Error storing latest used folder: %s", err->message);
2521 g_free (current_folder);
2527 gtk_widget_destroy (dialog);
2529 g_object_ref (window);
2530 /* The operation could take some time so allow the dialog to be closed */
2531 while (gtk_events_pending ())
2532 gtk_main_iteration ();
2534 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2536 GnomeVFSHandle *handle = NULL;
2537 GnomeVFSResult result;
2538 GtkTextIter position;
2539 GtkTextMark *insert_mark;
2541 uri = (const gchar *) uri_node->data;
2542 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2543 if (result == GNOME_VFS_OK) {
2545 GnomeVFSFileInfo *info;
2546 gchar *filename, *basename, *escaped_filename;
2547 TnyMimePart *mime_part;
2549 const gchar *mime_type = NULL;
2550 GnomeVFSURI *vfs_uri;
2551 guint64 stream_size;
2553 gnome_vfs_close (handle);
2554 vfs_uri = gnome_vfs_uri_new (uri);
2556 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2557 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2558 g_free (escaped_filename);
2559 gnome_vfs_uri_unref (vfs_uri);
2560 info = gnome_vfs_file_info_new ();
2562 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2563 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2565 mime_type = gnome_vfs_file_info_get_mime_type (info);
2567 mime_part = tny_platform_factory_new_mime_part
2568 (modest_runtime_get_platform_factory ());
2570 TnyStream *stream = create_stream_for_uri (uri);
2572 if (stream == NULL) {
2574 modest_platform_information_banner (NULL, NULL,
2575 _FM_OPENING_NOT_ALLOWED);
2577 g_object_unref (mime_part);
2578 gnome_vfs_file_info_unref (info);
2582 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2584 content_id = g_strdup_printf ("%d", priv->next_cid);
2585 tny_mime_part_set_content_id (mime_part, content_id);
2586 g_free (content_id);
2589 basename = g_path_get_basename (filename);
2590 tny_mime_part_set_filename (mime_part, basename);
2593 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2595 if (pixbuf != NULL) {
2596 priv->images_size += stream_size;
2597 priv->images_count ++;
2598 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2599 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2600 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2601 tny_mime_part_get_content_id (mime_part), pixbuf);
2602 g_object_unref (pixbuf);
2604 tny_list_prepend (priv->images, (GObject *) mime_part);
2605 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2607 modest_platform_information_banner (NULL, NULL,
2608 _("mail_ib_file_operation_failed"));
2612 g_object_unref (mime_part);
2613 gnome_vfs_file_info_unref (info);
2617 g_object_unref (window);
2621 on_attach_file_response (GtkDialog *dialog,
2625 GSList *uris = NULL;
2627 GnomeVFSFileSize total_size, allowed_size;
2628 ModestMsgEditWindow *window;
2629 ModestMsgEditWindowPrivate *priv;
2634 case GTK_RESPONSE_OK:
2636 gchar *current_folder;
2638 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2639 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2640 if (current_folder && current_folder != '\0') {
2642 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2643 current_folder, &err);
2645 g_debug ("Error storing latest used folder: %s", err->message);
2649 g_free (current_folder);
2656 window = MODEST_MSG_EDIT_WINDOW (user_data);
2657 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2659 /* allowed size is the maximum size - what's already there */
2660 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2661 &att_num, &att_size);
2662 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2665 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2667 const gchar *uri = (const gchar *) uri_node->data;
2670 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2672 if (total_size > allowed_size) {
2673 g_debug ("%s: total size: %u",
2674 __FUNCTION__, (unsigned int)total_size);
2677 allowed_size -= total_size;
2679 g_slist_foreach (uris, (GFunc) g_free, NULL);
2680 g_slist_free (uris);
2682 gtk_widget_destroy (GTK_WIDGET (dialog));
2686 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2688 GtkWidget *dialog = NULL;
2689 ModestMsgEditWindowPrivate *priv;
2692 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2694 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2696 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2699 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2700 _("mcen_ia_select_attachment_title"),
2701 (GtkWindow *) window,
2702 GTK_FILE_CHOOSER_ACTION_OPEN);
2703 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2704 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2705 if (conf_folder && conf_folder[0] != '\0') {
2706 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2709 /* Set the default folder to documents folder */
2710 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2711 #ifdef MODEST_TOOLKIT_HILDON2
2714 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2715 ".documents", NULL);
2718 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2719 g_free (docs_folder);
2721 g_free (conf_folder);
2722 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2723 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2724 GTK_WINDOW (dialog), GTK_WINDOW (window));
2726 /* Connect to response & show */
2727 g_signal_connect (dialog, "response",
2728 G_CALLBACK (on_attach_file_response), window);
2729 gtk_widget_show (dialog);
2734 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2736 GnomeVFSFileSize allowed_size)
2739 GnomeVFSHandle *handle = NULL;
2740 ModestMsgEditWindowPrivate *priv;
2741 GnomeVFSResult result;
2742 GnomeVFSFileSize size = 0;
2743 g_return_val_if_fail (window, 0);
2744 g_return_val_if_fail (uri, 0);
2746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2748 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2749 if (result == GNOME_VFS_OK) {
2750 TnyMimePart *mime_part;
2752 const gchar *mime_type = NULL;
2754 gchar *escaped_filename;
2757 GnomeVFSFileInfo *info;
2758 GnomeVFSURI *vfs_uri;
2760 gnome_vfs_close (handle);
2761 vfs_uri = gnome_vfs_uri_new (uri);
2764 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2765 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2766 g_free (escaped_filename);
2767 gnome_vfs_uri_unref (vfs_uri);
2769 info = gnome_vfs_file_info_new ();
2771 if (gnome_vfs_get_file_info (uri,
2773 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2775 mime_type = gnome_vfs_file_info_get_mime_type (info);
2776 mime_part = tny_platform_factory_new_mime_part
2777 (modest_runtime_get_platform_factory ());
2779 /* try to get the attachment's size; this may fail for weird
2780 * file systems, like obex, upnp... */
2781 if (allowed_size != 0 &&
2782 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2784 if (size > allowed_size) {
2785 modest_platform_information_banner (NULL, NULL,
2786 _("mail_ib_error_attachment_size"));
2791 g_debug ("%s: could not get attachment size", __FUNCTION__);
2793 stream = create_stream_for_uri (uri);
2795 if (stream == NULL) {
2797 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2799 g_object_unref (mime_part);
2801 gnome_vfs_file_info_unref (info);
2805 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2806 g_object_unref (stream);
2808 content_id = g_strdup_printf ("%d", priv->next_cid);
2809 tny_mime_part_set_content_id (mime_part, content_id);
2810 g_free (content_id);
2813 basename = g_path_get_basename (filename);
2814 tny_mime_part_set_filename (mime_part, basename);
2817 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2818 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2820 info->size == 0, info->size);
2821 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2822 gtk_widget_show_all (priv->attachments_caption);
2823 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2825 g_object_unref (mime_part);
2826 gnome_vfs_file_info_unref (info);
2833 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2836 ModestMsgEditWindowPrivate *priv;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2840 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2842 if (att_list == NULL) {
2843 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2844 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2845 g_object_unref (att_list);
2849 g_object_ref (att_list);
2852 if (tny_list_get_length (att_list) == 0) {
2853 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2855 gboolean dialog_response;
2856 gchar *message = NULL;
2857 gchar *filename = NULL;
2859 if (tny_list_get_length (att_list) == 1) {
2861 iter = tny_list_create_iterator (att_list);
2862 part = (TnyMimePart *) tny_iterator_get_current (iter);
2863 g_object_unref (iter);
2864 if (TNY_IS_MSG (part)) {
2865 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2867 filename = tny_header_dup_subject (header);
2868 g_object_unref (header);
2870 if (filename == NULL) {
2871 filename = g_strdup (_("mail_va_no_subject"));
2874 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2876 g_object_unref (part);
2878 filename = g_strdup ("");
2880 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2881 "emev_nc_delete_attachments",
2882 tny_list_get_length (att_list)), filename);
2885 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2889 if (dialog_response != GTK_RESPONSE_OK) {
2890 g_object_unref (att_list);
2894 for (iter = tny_list_create_iterator (att_list);
2895 !tny_iterator_is_done (iter);
2896 tny_iterator_next (iter)) {
2897 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2898 const gchar *att_id;
2899 tny_list_remove (priv->attachments, (GObject *) mime_part);
2901 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2903 if (tny_list_get_length (priv->attachments) == 0)
2904 gtk_widget_hide (priv->attachments_caption);
2905 att_id = tny_mime_part_get_content_id (mime_part);
2907 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2909 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2910 g_object_unref (mime_part);
2912 g_object_unref (iter);
2915 g_object_unref (att_list);
2917 /* if the last attachment has been removed, focus the Subject: field */
2918 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2919 gtk_widget_grab_focus (priv->subject_field);
2923 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2926 ModestMsgEditWindowPrivate *priv;
2929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2931 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2933 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2935 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2938 #ifndef MODEST_TOOLKIT_HILDON2
2940 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2943 ModestMsgEditWindowPrivate *priv;
2944 gint new_font_index;
2945 ModestMsgEditWindow *window;
2948 window = MODEST_MSG_EDIT_WINDOW (userdata);
2949 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2950 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2952 if (gtk_check_menu_item_get_active (menu_item)) {
2955 label = gtk_bin_get_child (GTK_BIN (menu_item));
2957 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2959 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2960 GINT_TO_POINTER(new_font_index)))
2961 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2963 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2964 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2965 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2972 font_size_clicked (GtkToolButton *button,
2973 ModestMsgEditWindow *window)
2975 #ifdef MODEST_TOOLKIT_HILDON2
2976 ModestMsgEditWindowPrivate *priv;
2977 GtkWidget *selector, *dialog;
2979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2981 selector = hildon_touch_selector_new ();
2982 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2983 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2985 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2986 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2987 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2989 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2993 WPTextBufferFormat format;
2995 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2997 memset (&format, 0, sizeof (format));
2998 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
3000 format.cs.font_size = TRUE;
3001 format.cs.text_position = TRUE;
3002 format.cs.font = TRUE;
3003 format.font_size = new_index;
3004 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
3006 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
3007 GINT_TO_POINTER (new_index)))
3008 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3010 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3011 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
3012 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
3013 size_text, "</span>", NULL);
3015 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
3019 gtk_widget_destroy (dialog);
3021 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3025 #ifdef MODEST_TOOLKIT_HILDON2
3027 font_face_clicked (GtkToolButton *button,
3028 ModestMsgEditWindow *window)
3030 ModestMsgEditWindowPrivate *priv;
3031 GtkWidget *selector, *dialog;
3032 GtkCellRenderer *renderer;
3034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3036 selector = hildon_touch_selector_new ();
3037 renderer = gtk_cell_renderer_text_new ();
3038 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3039 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3040 renderer, "family", 0, "text", 0, NULL);
3041 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3043 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3044 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3045 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3047 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3048 gint new_font_index;
3052 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3053 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3054 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3058 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3060 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3061 GINT_TO_POINTER(new_font_index)))
3062 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3064 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3065 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3067 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3071 gtk_tree_path_free (path);
3074 gtk_widget_destroy (dialog);
3076 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3081 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3084 ModestMsgEditWindowPrivate *priv = NULL;
3085 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3087 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3088 if (!priv->update_caption_visibility)
3091 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3093 gtk_widget_show (priv->cc_caption);
3095 gtk_widget_hide (priv->cc_caption);
3097 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3101 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3104 ModestMsgEditWindowPrivate *priv = NULL;
3105 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3107 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3108 if (!priv->update_caption_visibility)
3111 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3113 gtk_widget_show (priv->bcc_caption);
3115 gtk_widget_hide (priv->bcc_caption);
3117 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3121 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3122 ModestRecptEditor *editor)
3124 ModestMsgEditWindowPrivate *priv;
3126 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3127 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3129 /* we check for low-mem; in that case, show a warning, and don't allow
3130 * for the addressbook
3132 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3135 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3137 if (editor == NULL) {
3138 GtkWidget *view_focus, *parent;
3139 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3141 /* This code should be kept in sync with ModestRecptEditor. The
3142 textview inside the recpt editor is the one that really gets the
3143 focus. As it's inside a scrolled window, and this one inside the
3144 hbox recpt editor inherits from, we'll need to go up in the
3145 hierarchy to know if the text view is part of the recpt editor
3146 or if it's a different text entry */
3147 parent = gtk_widget_get_parent (view_focus);
3148 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3149 editor = MODEST_RECPT_EDITOR (parent);
3152 editor = MODEST_RECPT_EDITOR (priv->to_field);
3155 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3159 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3161 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3163 modest_msg_edit_window_open_addressbook (window, NULL);
3167 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3168 gboolean show_toolbar)
3170 ModestWindowPrivate *parent_priv;
3171 ModestMsgEditWindowPrivate *priv;
3173 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3175 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3177 /* We can not just use the code of
3178 modest_msg_edit_window_setup_toolbar because it has a
3179 mixture of both initialization and creation code. */
3181 gint current_format;
3182 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3183 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3184 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3185 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3187 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3190 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3192 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3193 if (modest_togglable_get_active (priv->show_toolbar_button) != show_toolbar) {
3194 modest_togglable_set_active (priv->show_toolbar_button, show_toolbar);
3199 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3200 TnyHeaderFlags priority_flags)
3202 ModestMsgEditWindowPrivate *priv;
3203 ModestWindowPrivate *parent_priv;
3205 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3208 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3210 if (priv->priority_flags != priority_flags) {
3211 GtkAction *priority_action = NULL;
3213 priv->priority_flags = priority_flags;
3215 switch (priority_flags) {
3216 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3217 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3218 MODEST_HEADER_ICON_HIGH,
3219 #ifdef MODEST_TOOLKIT_HILDON2
3220 HILDON_ICON_SIZE_SMALL
3222 GTK_ICON_SIZE_BUTTON
3225 gtk_widget_show (priv->priority_icon);
3226 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3227 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3229 case TNY_HEADER_FLAG_LOW_PRIORITY:
3230 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3231 MODEST_HEADER_ICON_LOW,
3232 #ifdef MODEST_TOOLKIT_HILDON2
3233 HILDON_ICON_SIZE_SMALL
3235 GTK_ICON_SIZE_BUTTON
3238 gtk_widget_show (priv->priority_icon);
3239 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3240 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3243 gtk_widget_hide (priv->priority_icon);
3244 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3245 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3248 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3249 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3251 gtk_widget_queue_resize (priv->subject_box);
3255 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3258 ModestMsgEditWindowPrivate *priv;
3259 ModestWindowPrivate *parent_priv;
3260 gint current_format;
3262 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3264 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3265 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3267 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3268 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3270 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3272 if (current_format != file_format) {
3273 switch (file_format) {
3274 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3275 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3276 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3277 update_signature (window, priv->last_from_account, priv->last_from_account);
3278 if (parent_priv->toolbar)
3279 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3280 MODEST_MSG_EDIT_WINDOW (window));
3282 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3285 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3286 if (response == GTK_RESPONSE_OK) {
3287 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3288 if (parent_priv->toolbar)
3289 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3290 MODEST_MSG_EDIT_WINDOW (window));
3292 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3293 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3298 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3299 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3300 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3305 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3307 #ifdef MODEST_TOOLKIT_HILDON2
3309 ModestMsgEditWindowPrivate *priv;
3310 WPTextBufferFormat oldfmt, fmt;
3311 gint old_position = 0;
3315 GdkColor *color = NULL;
3316 gboolean bold, bold_set, italic, italic_set;
3317 gboolean underline, underline_set;
3318 gboolean strikethrough, strikethrough_set;
3319 gboolean position_set;
3320 gboolean font_size_set, font_set, color_set;
3323 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3326 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3327 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3328 GTK_WINDOW(dialog), GTK_WINDOW (window));
3330 /* First we get the currently selected font information */
3331 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3333 switch (oldfmt.text_position) {
3334 case TEXT_POSITION_NORMAL:
3337 case TEXT_POSITION_SUPERSCRIPT:
3345 g_object_set (G_OBJECT (dialog),
3346 "bold", oldfmt.bold != FALSE,
3347 "bold-set", !oldfmt.cs.bold,
3348 "underline", oldfmt.underline != FALSE,
3349 "underline-set", !oldfmt.cs.underline,
3350 "italic", oldfmt.italic != FALSE,
3351 "italic-set", !oldfmt.cs.italic,
3352 "strikethrough", oldfmt.strikethrough != FALSE,
3353 "strikethrough-set", !oldfmt.cs.strikethrough,
3354 "color", &oldfmt.color,
3355 "color-set", !oldfmt.cs.color,
3356 "size", wp_font_size[oldfmt.font_size],
3357 "size-set", !oldfmt.cs.font_size,
3358 "position", old_position,
3359 "position-set", !oldfmt.cs.text_position,
3360 "family", wp_get_font_name (oldfmt.font),
3361 "family-set", !oldfmt.cs.font,
3364 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3365 GTK_WINDOW (dialog), GTK_WINDOW (window));
3366 gtk_widget_show_all (dialog);
3367 priv->font_dialog = dialog;
3368 response = gtk_dialog_run (GTK_DIALOG (dialog));
3369 priv->font_dialog = NULL;
3370 if (response == GTK_RESPONSE_OK) {
3372 g_object_get( dialog,
3374 "bold-set", &bold_set,
3375 "underline", &underline,
3376 "underline-set", &underline_set,
3378 "italic-set", &italic_set,
3379 "strikethrough", &strikethrough,
3380 "strikethrough-set", &strikethrough_set,
3382 "color-set", &color_set,
3384 "size-set", &font_size_set,
3385 "family", &font_name,
3386 "family-set", &font_set,
3387 "position", &position,
3388 "position-set", &position_set,
3393 if (response == GTK_RESPONSE_OK) {
3394 memset(&fmt, 0, sizeof(fmt));
3400 fmt.italic = italic;
3401 fmt.cs.italic = TRUE;
3403 if (underline_set) {
3404 fmt.underline = underline;
3405 fmt.cs.underline = TRUE;
3407 if (strikethrough_set) {
3408 fmt.strikethrough = strikethrough;
3409 fmt.cs.strikethrough = TRUE;
3414 ? TEXT_POSITION_NORMAL
3415 : ( ( position == 1 )
3416 ? TEXT_POSITION_SUPERSCRIPT
3417 : TEXT_POSITION_SUBSCRIPT );
3418 fmt.cs.text_position = TRUE;
3419 fmt.font_size = oldfmt.font_size;
3423 fmt.cs.color = TRUE;
3426 fmt.font = wp_get_font_index(font_name,
3431 if (font_size_set) {
3432 fmt.cs.font_size = TRUE;
3433 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3435 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3436 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3438 gtk_widget_destroy (dialog);
3440 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3445 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3447 ModestMsgEditWindowPrivate *priv;
3448 ModestWindowPrivate *parent_priv;
3449 gboolean was_rich_text, is_rich_text;