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 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
138 ModestRecptEditor *editor);
139 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
140 ModestMsgEditWindow *window);
142 /* ModestWindow methods implementation */
143 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
144 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
145 gboolean show_toolbar);
146 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
148 ModestMsgEditWindow *window);
149 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
150 static void subject_field_move_cursor (GtkEntry *entry,
151 GtkMovementStep step,
155 static void update_window_title (ModestMsgEditWindow *window);
158 static void modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
159 ModestMsgEditWindow *window);
160 static void modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
161 ModestMsgEditWindow *window);
162 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
164 GtkTextIter *match_start,
165 GtkTextIter *match_end);
167 static void remove_tags (WPTextBuffer *buffer);
169 static void on_account_removed (TnyAccountStore *account_store,
173 static void init_window (ModestMsgEditWindow *obj);
175 gboolean scroll_drag_timeout (gpointer userdata);
176 static void correct_scroll (ModestMsgEditWindow *w);
177 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
178 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
179 ModestMsgEditWindow *userdata);
180 static void text_buffer_mark_set (GtkTextBuffer *buffer,
183 ModestMsgEditWindow *userdata);
184 static void on_message_settings (GtkAction *action,
185 ModestMsgEditWindow *window);
186 static void setup_menu (ModestMsgEditWindow *self);
188 static void from_field_changed (GtkWidget *button,
189 ModestMsgEditWindow *self);
190 static void font_size_clicked (GtkToolButton *button,
191 ModestMsgEditWindow *window);
192 static void font_face_clicked (GtkToolButton *button,
193 ModestMsgEditWindow *window);
194 static void update_signature (ModestMsgEditWindow *self,
195 const gchar *old_account,
196 const gchar *new_account);
197 static void update_branding (ModestMsgEditWindow *self,
198 const gchar *new_account);
199 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
200 const gchar *label, GtkWidget *control);
201 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
202 static void DEBUG_BUFFER (WPTextBuffer *buffer)
206 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
208 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
209 while (!gtk_text_iter_is_end (&iter)) {
210 GString *output = g_string_new ("");
211 GSList *toggled_tags;
214 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
215 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
216 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
217 GtkTextTag *tag = (GtkTextTag *) node->data;
219 g_object_get (G_OBJECT (tag), "name", &name, NULL);
220 output = g_string_append (output, name);
221 g_string_append (output, " ");
223 output = g_string_append (output, "] OPENED [ ");
224 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
225 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
226 GtkTextTag *tag = (GtkTextTag *) node->data;
228 g_object_get (G_OBJECT (tag), "name", &name, NULL);
229 output = g_string_append (output, name);
230 g_string_append (output, " ");
232 output = g_string_append (output, "]\n");
233 g_debug ("%s", output->str);
234 g_string_free (output, TRUE);
235 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
237 g_debug ("END BUFFER");
241 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
242 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
246 /* static gboolean */
247 /* on_key_pressed (GtkWidget *self, */
248 /* GdkEventKey *event, */
249 /* gpointer user_data); */
251 /* list my signals */
258 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
259 struct _ModestMsgEditWindowPrivate {
261 GtkWidget *header_box;
263 ModestPairList *from_field_protos;
264 GtkWidget *from_field;
265 gchar *last_from_account;
266 gchar *original_account_name;
271 gchar *original_mailbox;
275 GtkWidget *bcc_field;
276 GtkWidget *subject_field;
277 GtkWidget *attachments_view;
278 GtkWidget *priority_icon;
279 GtkWidget *subject_box;
280 GtkWidget *send_button;
282 GtkWidget *cc_caption;
283 GtkWidget *bcc_caption;
284 gboolean update_caption_visibility;
285 GtkWidget *attachments_caption;
287 GtkTextBuffer *text_buffer;
289 GtkWidget *font_size_toolitem;
290 GtkWidget *font_face_toolitem;
291 GtkWidget *font_color_button;
292 GtkWidget *font_color_toolitem;
293 GSList *font_items_group;
294 GtkTreeModel *faces_model;
295 gint current_face_index;
296 GtkWidget *font_tool_button_label;
297 GtkTreeModel *sizes_model;
298 gint current_size_index;
299 GtkWidget *size_tool_button_label;
301 GtkWidget *isearch_toolbar;
304 GtkWidget *font_dialog;
306 GtkWidget *scrollable;
307 guint correct_scroll_idle;
308 guint scroll_drag_timeout_id;
312 TnyList *attachments;
317 TnyHeaderFlags priority_flags;
319 gboolean can_undo, can_redo;
320 gulong clipboard_change_handler_id;
321 gulong default_clipboard_change_handler_id;
322 gulong account_removed_handler_id;
323 guint clipboard_owner_idle;
324 gchar *clipboard_text;
333 GtkWidget *cc_button;
334 GtkWidget *bcc_button;
336 GtkWidget *max_chars_banner;
338 GtkWidget *brand_icon;
339 GtkWidget *brand_label;
340 GtkWidget *brand_container;
343 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
344 MODEST_TYPE_MSG_EDIT_WINDOW, \
345 ModestMsgEditWindowPrivate))
347 static GtkWindowClass *parent_class = NULL;
349 /* uncomment the following if you have defined any signals */
350 /* static guint signals[LAST_SIGNAL] = {0}; */
353 modest_msg_edit_window_get_type (void)
355 static GType my_type = 0;
357 static const GTypeInfo my_info = {
358 sizeof(ModestMsgEditWindowClass),
359 NULL, /* base init */
360 NULL, /* base finalize */
361 (GClassInitFunc) modest_msg_edit_window_class_init,
362 NULL, /* class finalize */
363 NULL, /* class data */
364 sizeof(ModestMsgEditWindow),
366 (GInstanceInitFunc) modest_msg_edit_window_init,
369 my_type = g_type_register_static (
370 #ifdef MODEST_TOOLKIT_HILDON2
371 MODEST_TYPE_HILDON2_WINDOW,
373 MODEST_TYPE_SHELL_WINDOW,
375 "ModestMsgEditWindow",
383 save_state (ModestWindow *self)
385 modest_widget_memory_save (modest_runtime_get_conf(),
386 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
391 restore_settings (ModestMsgEditWindow *self)
393 ModestConf *conf = NULL;
395 conf = modest_runtime_get_conf ();
397 /* Dim at start clipboard actions */
398 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
403 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
405 GObjectClass *gobject_class;
406 ModestWindowClass *modest_window_class;
407 gobject_class = (GObjectClass*) klass;
408 modest_window_class = (ModestWindowClass*) klass;
410 parent_class = g_type_class_peek_parent (klass);
411 gobject_class->finalize = modest_msg_edit_window_finalize;
413 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
414 modest_window_class->save_state_func = save_state;
415 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
417 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
421 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
423 ModestMsgEditWindowPrivate *priv;
424 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
426 priv->msg_body = NULL;
427 priv->from_field = NULL;
428 priv->to_field = NULL;
429 priv->cc_field = NULL;
430 priv->bcc_field = NULL;
431 priv->subject_field = NULL;
432 priv->attachments = TNY_LIST (tny_simple_list_new ());
433 priv->images = TNY_LIST (tny_simple_list_new ());
434 priv->images_size = 0;
435 priv->images_count = 0;
438 priv->cc_caption = NULL;
439 priv->bcc_caption = NULL;
440 priv->update_caption_visibility = FALSE;
442 priv->priority_flags = 0;
444 priv->isearch_toolbar = NULL;
445 priv->last_search = NULL;
447 priv->draft_msg = NULL;
448 priv->outbox_msg = NULL;
449 priv->msg_uid = NULL;
451 priv->can_undo = FALSE;
452 priv->can_redo = FALSE;
453 priv->clipboard_change_handler_id = 0;
454 priv->default_clipboard_change_handler_id = 0;
455 priv->account_removed_handler_id = 0;
456 priv->clipboard_owner_idle = 0;
457 priv->clipboard_text = NULL;
460 priv->scroll_drag_timeout_id = 0;
461 priv->correct_scroll_idle = 0;
462 priv->last_upper = 0.0;
464 priv->font_dialog = NULL;
465 priv->app_menu = NULL;
467 priv->references = NULL;
468 priv->in_reply_to = NULL;
469 priv->max_chars_banner = NULL;
471 if (!is_wp_text_buffer_started) {
472 is_wp_text_buffer_started = TRUE;
473 wp_text_buffer_library_init ();
477 #ifdef MODEST_TOOLKIT_HILDON2
478 hildon_program_add_window (hildon_program_get_instance(),
484 multimailbox_get_default_mailbox (const gchar *account_name)
486 gchar *transport_account;
487 gchar *result = NULL;
489 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
491 TNY_ACCOUNT_TYPE_TRANSPORT);
492 if (transport_account) {
494 ModestProtocolRegistry *registry;
496 registry = modest_runtime_get_protocol_registry ();
498 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
499 MODEST_ACCOUNT_PROTO, TRUE);
501 ModestProtocol *protocol =
502 modest_protocol_registry_get_protocol_by_name (registry,
503 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
505 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
506 ModestPairList *pair_list;
508 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
511 ModestPair *pair = (ModestPair *) pair_list->data;
512 result = g_strdup ((const gchar *) pair->first);
513 modest_pair_list_free (pair_list);
524 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
526 static ModestPairList*
527 get_transports (void)
529 GSList *transports = NULL;
531 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
532 GSList *accounts = modest_account_mgr_account_names (account_mgr,
533 TRUE /* only enabled accounts. */);
535 GSList *cursor = accounts;
537 gchar *account_name = cursor->data;
540 gchar *transport_account;
541 gboolean multi_mailbox = FALSE;
542 ModestProtocol *protocol = NULL;
544 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
546 transport_account = modest_account_mgr_get_server_account_name
547 (modest_runtime_get_account_mgr (),
549 TNY_ACCOUNT_TYPE_TRANSPORT);
550 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
551 ModestPairList *pair_list;
552 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
555 transports = g_slist_concat (transports, pair_list);
556 multi_mailbox = TRUE;
561 if (!multi_mailbox) {
562 gchar *from_string = NULL;
564 from_string = modest_account_mgr_get_from_string (account_mgr,
566 if (from_string && account_name) {
567 gchar *name = account_name;
568 ModestPair *pair = modest_pair_new ((gpointer) name,
569 (gpointer) from_string , TRUE);
570 transports = g_slist_prepend (transports, pair);
575 cursor = cursor->next;
577 g_slist_free (accounts); /* only free the accounts, not the elements,
578 * because they are used in the pairlist */
582 static void window_focus (GtkWindow *window,
586 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
590 scroll_drag_timeout (gpointer userdata)
592 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
593 ModestMsgEditWindowPrivate *priv;
595 /* It could happen that the window was already closed */
596 if (!GTK_WIDGET_VISIBLE (win))
599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
601 correct_scroll_without_drag_check (win, TRUE);
603 priv->scroll_drag_timeout_id = 0;
609 correct_scroll_without_drag_check_idle (gpointer userdata)
611 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
612 ModestMsgEditWindowPrivate *priv;
614 GdkRectangle rectangle;
615 gint offset_min, offset_max;
619 /* It could happen that the window was already closed */
620 if (!GTK_WIDGET_VISIBLE (w))
623 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
625 insert = gtk_text_buffer_get_insert (priv->text_buffer);
626 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
628 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
629 offset_min = priv->msg_body->allocation.y + rectangle.y;
630 offset_max = offset_min + rectangle.height;
632 vadj = modest_scrollable_get_vadjustment (MODEST_SCROLLABLE (priv->scrollable));
633 offset_min = MAX (offset_min - 48, 0);
634 offset_max = MIN (offset_max + 48, vadj->upper);
636 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
638 priv->correct_scroll_idle = 0;
643 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
645 ModestMsgEditWindowPrivate *priv;
647 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
649 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
652 if (priv->correct_scroll_idle > 0) {
656 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
657 (GSourceFunc) correct_scroll_without_drag_check_idle,
663 correct_scroll (ModestMsgEditWindow *w)
665 ModestMsgEditWindowPrivate *priv;
667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
668 if (gtk_grab_get_current () == priv->msg_body) {
669 if (priv->scroll_drag_timeout_id == 0) {
670 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
672 (GSourceFunc) scroll_drag_timeout,
679 correct_scroll_without_drag_check (w, TRUE);
683 text_buffer_end_user_action (GtkTextBuffer *buffer,
684 ModestMsgEditWindow *userdata)
687 correct_scroll (userdata);
691 text_buffer_mark_set (GtkTextBuffer *buffer,
694 ModestMsgEditWindow *userdata)
696 gtk_text_buffer_begin_user_action (buffer);
697 gtk_text_buffer_end_user_action (buffer);
701 cut_clipboard_check (GtkTextView *text_view,
704 GtkTextBuffer *buffer;
706 buffer = gtk_text_view_get_buffer (text_view);
707 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
708 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
713 copy_clipboard_check (GtkTextView *text_view,
716 GtkTextBuffer *buffer;
718 buffer = gtk_text_view_get_buffer (text_view);
719 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
720 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
725 attachment_deleted (ModestAttachmentsView *attachments_view,
728 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
733 body_size_request (GtkWidget *body,
737 /* Make sure the body always get at least 70 pixels */
738 if (req->height < 70)
743 connect_signals (ModestMsgEditWindow *obj)
745 ModestMsgEditWindowPrivate *priv;
747 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
749 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
750 G_CALLBACK (text_buffer_refresh_attributes), obj);
751 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
752 G_CALLBACK (text_buffer_can_undo), obj);
753 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
754 G_CALLBACK (text_buffer_can_redo), obj);
755 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
756 G_CALLBACK (body_changed), obj);
757 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
758 G_CALLBACK (body_insert_text), obj);
759 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
760 G_CALLBACK (body_changed), obj);
761 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
762 G_CALLBACK (text_buffer_end_user_action), obj);
763 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
764 G_CALLBACK (text_buffer_mark_set), obj);
765 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
766 G_CALLBACK (text_buffer_apply_tag), obj);
767 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
768 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
769 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
770 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
771 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
772 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
774 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
775 G_CALLBACK (modest_ui_actions_on_send), obj);
777 if (GTK_IS_COMBO_BOX (priv->from_field)) {
778 g_signal_connect (G_OBJECT (priv->from_field), "changed",
779 G_CALLBACK (from_field_changed), obj);
781 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
782 G_CALLBACK (from_field_changed), obj);
785 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
786 G_CALLBACK (msg_body_focus), obj);
787 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
788 G_CALLBACK (msg_body_focus), obj);
789 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
790 G_CALLBACK (body_size_request), obj);
791 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
792 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
793 "changed", G_CALLBACK (recpt_field_changed), obj);
794 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
795 "changed", G_CALLBACK (recpt_field_changed), obj);
796 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
797 "changed", G_CALLBACK (recpt_field_changed), obj);
798 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
799 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
800 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
802 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-search",
803 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_search), obj);
804 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-close",
805 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_close), obj);
807 priv->clipboard_change_handler_id =
808 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
809 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
810 priv->default_clipboard_change_handler_id =
811 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
812 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
814 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
815 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
816 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
820 init_wp_text_view_style ()
822 static gboolean initialized = FALSE;
825 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
831 init_window (ModestMsgEditWindow *obj)
833 GtkWidget *to_caption, *subject_caption;
834 GtkWidget *main_vbox;
835 ModestMsgEditWindowPrivate *priv;
836 GtkActionGroup *action_group;
837 ModestWindowPrivate *parent_priv;
838 GError *error = NULL;
840 GtkSizeGroup *title_size_group;
841 GtkSizeGroup *value_size_group;
842 GtkWidget *window_box;
843 GtkWidget *window_align;
844 #if (GTK_MINOR_VERSION >= 10)
845 GdkAtom deserialize_type;
847 GtkWidget *from_send_hbox;
848 GtkWidget *send_icon;
849 GtkWidget *attachments_label;
850 GtkWidget *branding_box;
851 GtkWidget *from_caption;
853 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
854 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
856 parent_priv->ui_manager = gtk_ui_manager_new();
857 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
858 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
860 /* Add common actions */
861 gtk_action_group_add_actions (action_group,
862 modest_msg_edit_action_entries,
863 G_N_ELEMENTS (modest_msg_edit_action_entries),
865 gtk_action_group_add_actions (action_group,
866 hildon2_msg_edit_action_entries,
867 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
869 gtk_action_group_add_toggle_actions (action_group,
870 modest_msg_edit_toggle_action_entries,
871 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
873 gtk_action_group_add_radio_actions (action_group,
874 modest_msg_edit_alignment_radio_action_entries,
875 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
877 G_CALLBACK (modest_ui_actions_on_change_justify),
879 gtk_action_group_add_radio_actions (action_group,
880 modest_msg_edit_priority_action_entries,
881 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
883 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
885 gtk_action_group_add_radio_actions (action_group,
886 modest_msg_edit_file_format_action_entries,
887 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
888 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
889 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
891 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
892 g_object_unref (action_group);
894 /* Load the UI definition */
895 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
898 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
899 g_clear_error (&error);
902 parent_priv->menubar = NULL;
904 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
905 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
907 /* Note: This ModestPairList* must exist for as long as the picker
908 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
909 * so it can't know how to manage its memory. */
910 priv->from_field = modest_toolkit_factory_create_selector (modest_runtime_get_toolkit_factory (),
912 modest_selector_set_value_max_chars (priv->from_field, MAX_FROM_VALUE);
913 if (GTK_IS_COMBO_BOX (priv->from_field)) {
914 from_caption = modest_toolkit_utils_create_captioned (title_size_group, NULL,
915 _("mail_va_from"), FALSE,
917 gtk_widget_show (from_caption);
919 #ifdef MODEST_TOOLKIT_HILDON2
920 modest_toolkit_utils_set_hbutton_layout (title_size_group, NULL,
921 _("mail_va_from"), priv->from_field);
922 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
923 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
924 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
925 from_caption = priv->from_field;
929 priv->to_field = modest_recpt_editor_new ();
930 priv->cc_field = modest_recpt_editor_new ();
931 priv->bcc_field = modest_recpt_editor_new ();
932 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
933 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
934 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
935 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
936 priv->priority_icon = gtk_image_new ();
937 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
938 priv->subject_field = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
939 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
940 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
941 modest_entry_set_hint (priv->subject_field, _("mail_va_no_subject"));
943 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
944 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
946 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
947 priv->attachments_view = modest_attachments_view_new (NULL);
948 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
949 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
951 priv->header_box = gtk_vbox_new (FALSE, 0);
953 to_caption = _create_addressbook_box
954 (title_size_group, value_size_group,
955 _("mail_va_to"), priv->to_field);
956 priv->cc_caption = _create_addressbook_box
957 (title_size_group, value_size_group,
958 _("mail_va_cc"), priv->cc_field);
959 priv->bcc_caption = _create_addressbook_box
960 (title_size_group, value_size_group,
961 _("mail_va_hotfix1"), priv->bcc_field);
962 subject_caption = modest_toolkit_utils_create_captioned (title_size_group, value_size_group,
963 _("mail_va_subject"), FALSE, priv->subject_box);
964 priv->attachments_caption = modest_toolkit_utils_create_captioned_with_size_type (NULL, NULL,
965 _("mail_va_attachment"),
967 priv->attachments_view,
968 #ifdef MODEST_TOOLKIT_HILDON2
969 HILDON_SIZE_AUTO_WIDTH |
970 HILDON_SIZE_AUTO_HEIGHT
975 attachments_label = modest_toolkit_utils_captioned_get_label_widget (priv->attachments_caption);
977 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
981 #ifdef MODEST_TOOLKIT_HILDON2
982 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
983 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
985 priv->send_button = gtk_button_new ();
986 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, GTK_ICON_SIZE_BUTTON);
988 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
989 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
991 g_object_unref (title_size_group);
992 g_object_unref (value_size_group);
994 priv->brand_icon = gtk_image_new ();
995 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
996 priv->brand_label = gtk_label_new (NULL);
997 #ifdef MODEST_TOOLKIT_HILDON2
998 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
1000 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
1001 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
1002 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
1004 from_send_hbox = gtk_hbox_new (FALSE, 0);
1005 gtk_box_pack_start (GTK_BOX (from_send_hbox), from_caption, TRUE, TRUE, 0);
1006 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1008 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1009 gtk_widget_show (branding_box);
1010 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1011 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1013 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1014 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1015 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1016 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1019 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1020 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1021 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1022 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1023 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1024 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1025 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1026 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1028 init_wp_text_view_style ();
1030 priv->msg_body = modest_wp_text_view_new ();
1033 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1034 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1035 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1036 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1037 #if (GTK_MINOR_VERSION >= 10)
1038 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1039 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1041 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1042 deserialize_type, TRUE);
1044 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1046 priv->isearch_toolbar = modest_toolkit_factory_create_isearch_toolbar (modest_runtime_get_toolkit_factory (),
1048 gtk_widget_set_no_show_all (priv->isearch_toolbar, TRUE);
1050 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1052 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1054 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1056 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1057 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1058 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1060 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1061 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1062 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1064 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1065 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1067 window_box = gtk_vbox_new (FALSE, 0);
1068 gtk_container_add (GTK_CONTAINER(obj), window_box);
1070 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1075 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1077 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1079 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1080 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1081 priv->clipboard_change_handler_id))
1082 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1083 priv->clipboard_change_handler_id);
1084 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1085 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1086 priv->default_clipboard_change_handler_id))
1087 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1088 priv->default_clipboard_change_handler_id);
1090 if (priv->account_removed_handler_id &&
1091 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1092 priv->account_removed_handler_id))
1093 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1094 priv->account_removed_handler_id);
1098 modest_msg_edit_window_finalize (GObject *obj)
1100 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1102 if (priv->max_chars_banner) {
1103 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1104 priv->max_chars_banner = FALSE;
1107 /* Sanity check: shouldn't be needed, the window mgr should
1108 call this function before */
1109 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1111 if (priv->font_dialog != NULL) {
1112 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1115 if (priv->clipboard_text != NULL) {
1116 g_free (priv->clipboard_text);
1117 priv->clipboard_text = NULL;
1120 if (priv->draft_msg != NULL) {
1121 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1122 if (TNY_IS_HEADER (header)) {
1123 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1124 modest_window_mgr_unregister_header (mgr, header);
1126 g_object_unref (priv->draft_msg);
1127 priv->draft_msg = NULL;
1129 if (priv->outbox_msg != NULL) {
1130 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1131 if (TNY_IS_HEADER (header)) {
1132 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1133 modest_window_mgr_unregister_header (mgr, header);
1135 g_object_unref (priv->outbox_msg);
1136 priv->outbox_msg = NULL;
1138 if (priv->correct_scroll_idle > 0) {
1139 g_source_remove (priv->correct_scroll_idle);
1140 priv->correct_scroll_idle = 0;
1142 if (priv->scroll_drag_timeout_id > 0) {
1143 g_source_remove (priv->scroll_drag_timeout_id);
1144 priv->scroll_drag_timeout_id = 0;
1146 if (priv->clipboard_owner_idle > 0) {
1147 g_source_remove (priv->clipboard_owner_idle);
1148 priv->clipboard_owner_idle = 0;
1150 if (priv->original_account_name)
1151 g_free (priv->original_account_name);
1152 if (priv->original_mailbox)
1153 g_free (priv->original_mailbox);
1154 g_free (priv->msg_uid);
1155 g_free (priv->last_search);
1156 g_free (priv->references);
1157 g_free (priv->in_reply_to);
1158 g_object_unref (priv->attachments);
1159 g_object_unref (priv->images);
1161 /* This had to stay alive for as long as the picker that used it: */
1162 modest_pair_list_free (priv->from_field_protos);
1164 G_OBJECT_CLASS(parent_class)->finalize (obj);
1168 pixbuf_size_prepared (GdkPixbufLoader *loader,
1171 ModestMsgEditWindow *self)
1173 gint new_height, new_width;
1176 new_height = height;
1180 if (width > IMAGE_MAX_WIDTH) {
1181 new_height = height * IMAGE_MAX_WIDTH / width;
1182 new_width = IMAGE_MAX_WIDTH;
1185 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1189 pixbuf_from_stream (TnyStream *stream,
1190 const gchar *mime_type,
1191 guint64 *stream_size,
1192 ModestMsgEditWindow *self)
1194 GdkPixbufLoader *loader;
1197 GError *error = NULL;
1201 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1203 if (loader == NULL) {
1208 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1210 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1212 tny_stream_reset (TNY_STREAM (stream));
1213 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1214 unsigned char read_buffer[128];
1216 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1218 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1221 /* Allow some UI responsiveness */
1222 while (gtk_events_pending ())
1223 gtk_main_iteration ();
1225 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1227 gdk_pixbuf_loader_close (loader, &error);
1230 g_error_free (error);
1231 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1233 g_object_ref (pixbuf);
1234 g_object_unref (loader);
1239 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1240 GdkPixbuf *new_pixbuf;
1242 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1243 gdk_pixbuf_get_width (pixbuf);
1244 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1245 g_object_unref (pixbuf);
1246 pixbuf = new_pixbuf;
1250 *stream_size = size;
1256 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1258 ModestMsgEditWindowPrivate *priv;
1261 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1263 g_object_ref (self);
1264 for (iter = tny_list_create_iterator (attachments);
1265 !tny_iterator_is_done (iter);
1266 tny_iterator_next (iter)) {
1267 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1268 const gchar *cid = tny_mime_part_get_content_id (part);
1269 const gchar *mime_type = tny_mime_part_get_content_type (part);
1270 if ((cid != NULL)&&(mime_type != NULL)) {
1271 guint64 stream_size;
1272 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1273 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1276 g_object_unref (stream);
1278 if (pixbuf != NULL) {
1279 priv->images_count ++;
1280 priv->images_size += stream_size;
1281 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1282 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1284 g_object_unref (pixbuf);
1287 g_object_unref (part);
1289 g_object_unref (iter);
1290 g_object_unref (self);
1294 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1296 TnyMimePart *parent = NULL;
1297 const gchar *content_type = NULL;
1298 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1300 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1302 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1303 parent = g_object_ref (msg);
1304 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1305 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1308 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1309 iter = tny_list_create_iterator (parts);
1310 while (!tny_iterator_is_done (iter)) {
1312 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1313 content_type = tny_mime_part_get_content_type (part);
1314 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1318 g_object_unref (part);
1320 tny_iterator_next (iter);
1322 g_object_unref (iter);
1323 g_object_unref (parts);
1326 if (parent != NULL) {
1327 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1330 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1331 iter = tny_list_create_iterator (parts);
1332 while (!tny_iterator_is_done (iter)) {
1334 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1335 content_type = tny_mime_part_get_content_type (part);
1336 if (content_type && g_str_has_prefix (content_type, "image/")) {
1337 tny_list_prepend (priv->images, (GObject *) part);
1339 g_object_unref (part);
1340 tny_iterator_next (iter);
1342 g_object_unref (iter);
1343 g_object_unref (parts);
1344 g_object_unref (parent);
1349 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1352 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1354 for (iter = tny_list_create_iterator (attachments) ;
1355 !tny_iterator_is_done (iter);
1356 tny_iterator_next (iter)) {
1357 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1358 const gchar *cid = tny_mime_part_get_content_id (part);
1360 char *invalid = NULL;
1361 gint int_cid = strtol (cid, &invalid, 10);
1362 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1363 priv->next_cid = int_cid + 1;
1366 g_object_unref (part);
1368 g_object_unref (iter);
1372 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1375 gchar *to, *cc, *bcc, *subject;
1377 ModestMsgEditWindowPrivate *priv;
1378 ModestWindowPrivate *parent_priv;
1380 TnyHeaderFlags priority_flags;
1381 TnyFolder *msg_folder;
1382 gboolean is_html = FALSE;
1383 gboolean field_view_set;
1385 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1386 g_return_if_fail (TNY_IS_MSG (msg));
1388 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1389 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1391 header = tny_msg_get_header (msg);
1392 to = tny_header_dup_to (header);
1393 cc = tny_header_dup_cc (header);
1394 bcc = tny_header_dup_bcc (header);
1395 subject = tny_header_dup_subject (header);
1397 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1398 priority_flags = tny_header_get_priority (header);
1401 gchar *quoted_names = modest_text_utils_quote_names (to);
1402 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1403 g_free (quoted_names);
1406 field_view_set = TRUE;
1408 gchar *quoted_names = modest_text_utils_quote_names (cc);
1409 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1410 g_free (quoted_names);
1411 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1412 gtk_widget_show (priv->cc_caption);
1413 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1414 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1415 gtk_widget_hide (priv->cc_caption);
1416 field_view_set = FALSE;
1418 modest_togglable_set_active (priv->cc_button, field_view_set);
1420 field_view_set = TRUE;
1422 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1423 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1424 g_free (quoted_names);
1425 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1426 gtk_widget_show (priv->bcc_caption);
1427 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1428 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1429 gtk_widget_hide (priv->bcc_caption);
1430 field_view_set = FALSE;
1432 modest_togglable_set_active (priv->bcc_button, field_view_set);
1436 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1437 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1440 update_window_title (self);
1442 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1443 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1445 if ((body == NULL)||(body[0] == '\0')) {
1447 body = modest_text_utils_convert_to_html ("");
1450 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1451 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1454 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1457 /* Add attachments to the view */
1458 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1459 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1460 if (tny_list_get_length (priv->attachments) == 0) {
1461 gtk_widget_hide (priv->attachments_caption);
1463 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1464 gtk_widget_show_all (priv->attachments_caption);
1466 get_related_images (self, msg);
1467 update_next_cid (self, priv->attachments);
1468 update_next_cid (self, priv->images);
1469 replace_with_images (self, priv->images);
1471 if (preserve_is_rich && !is_html) {
1472 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1473 /* Get the default format required from configuration */
1474 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1475 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1478 /* Set the default focus depending on having already a To: field or not */
1479 if ((!to)||(*to == '\0')) {
1480 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1482 gtk_widget_grab_focus (priv->msg_body);
1485 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1487 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1488 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1490 modest_msg_edit_window_set_modified (self, FALSE);
1492 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1493 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1494 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1495 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1497 if (priv->msg_uid) {
1498 g_free (priv->msg_uid);
1499 priv->msg_uid = NULL;
1502 /* we should set a reference to the incoming message if it is a draft */
1503 msg_folder = tny_msg_get_folder (msg);
1505 if (modest_tny_folder_is_local_folder (msg_folder)) {
1506 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1507 if (type == TNY_FOLDER_TYPE_INVALID)
1508 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1510 if (type == TNY_FOLDER_TYPE_DRAFTS)
1511 priv->draft_msg = g_object_ref(msg);
1512 if (type == TNY_FOLDER_TYPE_OUTBOX)
1513 priv->outbox_msg = g_object_ref(msg);
1514 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1516 g_object_unref (msg_folder);
1526 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1528 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1529 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1530 GtkWidget *placeholder;
1531 GtkWidget *tool_item;
1536 GtkWidget *sizes_menu;
1537 GtkWidget *fonts_menu;
1543 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1544 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1545 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1546 #ifdef MODEST_TOOLKIT_HILDON2
1547 HILDON_ICON_SIZE_FINGER
1549 GTK_ICON_SIZE_LARGE_TOOLBAR
1552 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1554 /* Font color placeholder */
1555 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1556 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1559 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1560 #ifdef MODEST_TOOLKIT_HILDON2
1561 priv->font_color_button = modest_color_button_new ();
1563 priv->font_color_button = gtk_color_button_new ();
1565 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1566 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1567 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1568 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1569 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1570 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1571 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1572 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1574 G_CALLBACK (modest_msg_edit_window_color_button_change),
1577 /* Font size and face placeholder */
1578 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1579 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1581 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1582 priv->size_tool_button_label = gtk_label_new (NULL);
1583 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1584 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1585 size_text, "</span>", NULL);
1586 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1587 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1589 #ifdef MODEST_TOOLKIT_HILDON2
1590 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1592 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1593 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1594 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1595 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1596 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1597 gtk_widget_set_sensitive (arrow, FALSE);
1598 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1599 sizes_menu = gtk_menu_new ();
1600 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1601 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1604 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1605 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1607 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1611 if (wp_font_size[size_index] == 12)
1612 priv->current_size_index = size_index;
1616 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1617 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1618 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1619 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1620 priv->font_size_toolitem = tool_item;
1623 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1624 priv->font_tool_button_label = gtk_label_new (NULL);
1625 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1626 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1627 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1629 #ifdef MODEST_TOOLKIT_HILDON2
1630 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1632 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1633 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1634 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1635 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1636 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1637 gtk_widget_set_sensitive (arrow, FALSE);
1638 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1639 fonts_menu = gtk_menu_new ();
1640 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1641 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1644 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1646 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1647 0, wp_get_font_name (font_index),
1650 if (font_index == DEFAULT_FONT)
1651 priv->current_face_index = font_index;
1653 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1654 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1655 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1656 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1657 priv->font_face_toolitem = tool_item;
1659 /* Set expand and homogeneous for remaining items */
1660 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1661 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1662 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1663 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1664 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1665 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1667 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1668 will not show the tool items added to the placeholders) */
1669 gtk_widget_show_all (parent_priv->toolbar);
1671 /* Set the no show all *after* showing all items. We do not
1672 want the toolbar to be shown with a show all because it
1673 could go agains the gconf setting regarding showing or not
1674 the toolbar of the editor window */
1675 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1681 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1684 ModestWindowPrivate *parent_priv;
1685 ModestMsgEditWindowPrivate *priv;
1686 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1687 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1688 ModestWindowMgr *mgr = NULL;
1690 g_return_val_if_fail (msg, NULL);
1691 g_return_val_if_fail (account_name, NULL);
1693 mgr = modest_runtime_get_window_mgr ();
1695 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1697 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1698 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1700 /* Menubar. Update the state of some toggles */
1701 priv->from_field_protos = get_transports ();
1702 priv->original_mailbox = NULL;
1703 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1704 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1705 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1706 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1707 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1708 priv->original_mailbox = g_strdup (mailbox);
1709 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1710 /* We set the first mailbox as the active mailbox */
1711 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1712 if (priv->original_mailbox != NULL)
1713 modest_selector_set_active_id (priv->from_field,
1714 (gpointer) priv->original_mailbox);
1716 modest_selector_set_active_id (priv->from_field,
1717 (gpointer) account_name);
1719 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1721 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1722 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1723 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1724 #ifdef HILDON_TOOLKIT_HILDON2
1725 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1727 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1728 hildon_touch_selector_get_current_text
1729 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1732 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1733 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1736 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1738 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1740 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1741 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1743 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1745 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1746 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1747 /* Add common dimming rules */
1748 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1749 modest_msg_edit_window_toolbar_dimming_entries,
1750 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1751 MODEST_WINDOW (obj));
1752 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1753 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1754 MODEST_WINDOW (obj));
1755 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1756 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1757 MODEST_WINDOW (obj));
1758 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1759 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1760 MODEST_WINDOW (obj));
1761 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1762 G_CALLBACK (modest_ui_dimming_rules_on_send),
1763 MODEST_WINDOW (obj));
1764 /* Insert dimming rules group for this window */
1765 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1766 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1768 /* Setup app menu */
1769 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1771 /* Checks the dimming rules */
1772 g_object_unref (toolbar_rules_group);
1773 g_object_unref (clipboard_rules_group);
1774 gtk_widget_hide (priv->priority_icon);
1775 gtk_widget_queue_resize (priv->subject_box);
1776 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1778 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1780 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1781 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1782 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1783 priv->update_caption_visibility = TRUE;
1785 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1787 /* Track account-removed signal, this window should be closed
1788 in the case we're creating a mail associated to the account
1790 priv->account_removed_handler_id =
1791 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1793 G_CALLBACK(on_account_removed),
1796 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1798 return (ModestWindow*) obj;
1802 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1804 GString **string_buffer = (GString **) user_data;
1806 *string_buffer = g_string_append (*string_buffer, buffer);
1812 * @result: A new string which should be freed with g_free().
1815 get_formatted_data (ModestMsgEditWindow *edit_window)
1817 ModestMsgEditWindowPrivate *priv;
1818 GString *string_buffer = g_string_new ("");
1820 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1822 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1824 modest_text_utils_hyperlinkify (string_buffer);
1826 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1828 return g_string_free (string_buffer, FALSE);
1833 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1836 const gchar *account_name;
1837 ModestMsgEditWindowPrivate *priv;
1838 TnyIterator *att_iter;
1839 const gchar *picker_active_id;
1841 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1843 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1845 picker_active_id = modest_selector_get_active_id (priv->from_field);
1846 g_return_val_if_fail (picker_active_id, NULL);
1847 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1849 /* don't free these (except from) */
1850 data = g_slice_new0 (MsgData);
1851 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
1852 data->account_name = g_strdup (account_name);
1853 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1854 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1855 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1856 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1857 data->references = g_strdup (priv->references);
1858 data->in_reply_to = g_strdup (priv->in_reply_to);
1859 if (priv->draft_msg) {
1860 data->draft_msg = g_object_ref (priv->draft_msg);
1861 } else if (priv->outbox_msg) {
1862 data->draft_msg = g_object_ref (priv->outbox_msg);
1864 data->draft_msg = NULL;
1867 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1869 gtk_text_buffer_get_bounds (buf, &b, &e);
1870 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1872 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1873 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1875 data->html_body = NULL;
1877 /* deep-copy the data */
1878 att_iter = tny_list_create_iterator (priv->attachments);
1879 data->attachments = NULL;
1880 while (!tny_iterator_is_done (att_iter)) {
1881 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1882 if (!(TNY_IS_MIME_PART(part))) {
1883 g_warning ("strange data in attachment list");
1884 g_object_unref (part);
1885 tny_iterator_next (att_iter);
1888 data->attachments = g_list_append (data->attachments,
1890 tny_iterator_next (att_iter);
1892 g_object_unref (att_iter);
1894 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1895 att_iter = tny_list_create_iterator (priv->images);
1896 data->images = NULL;
1897 while (!tny_iterator_is_done (att_iter)) {
1898 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1900 if (!(TNY_IS_MIME_PART(part))) {
1901 g_warning ("strange data in attachment list");
1902 g_object_unref (part);
1903 tny_iterator_next (att_iter);
1906 cid = tny_mime_part_get_content_id (part);
1908 gchar *image_tag_id;
1909 GtkTextTag *image_tag;
1911 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1912 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1913 g_free (image_tag_id);
1915 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1917 ((gtk_text_iter_has_tag (&iter, image_tag))||
1918 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1919 data->images = g_list_append (data->images,
1920 g_object_ref (part));
1922 g_object_unref (part);
1923 tny_iterator_next (att_iter);
1925 g_object_unref (att_iter);
1927 data->priority_flags = priv->priority_flags;
1934 unref_gobject (GObject *obj, gpointer data)
1936 if (!G_IS_OBJECT(obj))
1938 g_object_unref (obj);
1942 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1945 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1953 g_free (data->from);
1954 g_free (data->subject);
1955 g_free (data->plain_body);
1956 g_free (data->html_body);
1957 g_free (data->account_name);
1958 g_free (data->references);
1959 g_free (data->in_reply_to);
1961 if (data->draft_msg != NULL) {
1962 g_object_unref (data->draft_msg);
1963 data->draft_msg = NULL;
1966 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1967 g_list_free (data->attachments);
1968 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1969 g_list_free (data->images);
1971 g_slice_free (MsgData, data);
1975 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1977 guint64 *parts_size)
1979 ModestMsgEditWindowPrivate *priv;
1981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1983 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1985 /* TODO: add images */
1986 *parts_size += priv->images_size;
1987 *parts_count += priv->images_count;
1992 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1995 ModestMsgEditWindowPrivate *priv = NULL;
1996 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1998 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2000 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2002 return MODEST_MSG_EDIT_FORMAT_HTML;
2004 return MODEST_MSG_EDIT_FORMAT_TEXT;
2008 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2009 ModestMsgEditFormat format)
2011 ModestMsgEditWindowPrivate *priv;
2012 ModestWindowPrivate *parent_priv;
2014 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2015 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2016 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2019 case MODEST_MSG_EDIT_FORMAT_HTML:
2020 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2021 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
2023 case MODEST_MSG_EDIT_FORMAT_TEXT:
2024 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2025 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
2028 g_return_if_reached ();
2032 ModestMsgEditFormatState *
2033 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2035 ModestMsgEditFormatState *format_state = NULL;
2036 ModestMsgEditWindowPrivate *priv;
2037 WPTextBufferFormat *buffer_format;
2039 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2041 buffer_format = g_new0 (WPTextBufferFormat, 1);
2042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2044 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2046 format_state = g_new0 (ModestMsgEditFormatState, 1);
2047 format_state->bold = buffer_format->bold&0x1;
2048 format_state->italics = buffer_format->italic&0x1;
2049 format_state->bullet = buffer_format->bullet&0x1;
2050 format_state->color = buffer_format->color;
2051 format_state->font_size = buffer_format->font_size;
2052 format_state->font_family = wp_get_font_name (buffer_format->font);
2053 format_state->justification = buffer_format->justification;
2054 g_free (buffer_format);
2056 return format_state;
2061 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2062 const ModestMsgEditFormatState *format_state)
2064 ModestMsgEditWindowPrivate *priv;
2065 WPTextBufferFormat *buffer_format;
2066 WPTextBufferFormat *current_format;
2068 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2069 g_return_if_fail (format_state != NULL);
2071 buffer_format = g_new0 (WPTextBufferFormat, 1);
2072 current_format = g_new0 (WPTextBufferFormat, 1);
2074 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2075 gtk_widget_grab_focus (priv->msg_body);
2076 buffer_format->bold = (format_state->bold != FALSE);
2077 buffer_format->italic = (format_state->italics != FALSE);
2078 buffer_format->color = format_state->color;
2079 buffer_format->font_size = format_state->font_size;
2080 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2081 buffer_format->justification = format_state->justification;
2082 buffer_format->bullet = format_state->bullet;
2084 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2086 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2087 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2088 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2089 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2090 buffer_format->cs.font = (buffer_format->font != current_format->font);
2091 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2092 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2094 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2095 if (buffer_format->cs.bold) {
2096 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2097 GINT_TO_POINTER (buffer_format->bold&0x1));
2099 if (buffer_format->cs.italic) {
2100 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2101 GINT_TO_POINTER (buffer_format->italic&0x1));
2103 if (buffer_format->cs.color) {
2104 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2105 GINT_TO_POINTER (&(buffer_format->color)));
2107 if (buffer_format->cs.font_size) {
2108 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2109 GINT_TO_POINTER (buffer_format->font_size));
2111 if (buffer_format->cs.justification) {
2112 switch (buffer_format->justification) {
2113 case GTK_JUSTIFY_LEFT:
2114 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2115 GINT_TO_POINTER(TRUE));
2117 case GTK_JUSTIFY_CENTER:
2118 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2119 GINT_TO_POINTER(TRUE));
2121 case GTK_JUSTIFY_RIGHT:
2122 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2123 GINT_TO_POINTER(TRUE));
2130 if (buffer_format->cs.font) {
2131 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2132 GINT_TO_POINTER (buffer_format->font));
2134 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2135 if (buffer_format->cs.bullet) {
2136 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2137 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2139 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2141 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2143 g_free (buffer_format);
2144 g_free (current_format);
2146 /* Check dimming rules */
2147 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2148 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2152 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2154 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2156 ModestWindowPrivate *parent_priv;
2157 ModestMsgEditWindowPrivate *priv;
2159 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2160 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2162 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2163 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2164 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2165 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2167 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2168 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2169 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2172 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2174 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2175 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2177 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2178 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2180 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2181 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2184 switch (buffer_format->justification)
2186 case GTK_JUSTIFY_LEFT:
2187 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2189 case GTK_JUSTIFY_CENTER:
2190 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2192 case GTK_JUSTIFY_RIGHT:
2193 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2200 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2202 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2203 G_CALLBACK (modest_msg_edit_window_color_button_change),
2205 #ifdef MODEST_TOOLKIT_HILDON2
2206 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2208 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2210 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2211 G_CALLBACK (modest_msg_edit_window_color_button_change),
2214 if (priv->current_size_index != buffer_format->font_size) {
2218 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2219 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2223 priv->current_size_index = buffer_format->font_size;
2225 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2226 markup = g_strconcat ("<span font_family='Sans'>",
2227 size_text, "</span>", NULL);
2229 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2233 gtk_tree_path_free (path);
2236 if (priv->current_face_index != buffer_format->font) {
2240 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2241 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2245 priv->current_face_index = buffer_format->font;
2246 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2247 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2248 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2255 g_free (buffer_format);
2261 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2263 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2264 ModestMsgEditWindowPrivate *priv;
2265 GtkWidget *dialog = NULL;
2267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2268 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2270 #ifdef MODEST_TOOLKIT_HILDON2
2271 dialog = hildon_color_chooser_new ();
2272 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2273 g_free (buffer_format);
2275 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2277 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2278 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2281 gtk_widget_destroy (dialog);
2283 dialog = gtk_color_selection_dialog_new (NULL);
2284 GtkWidget *selection;
2286 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2287 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2288 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2289 g_free (buffer_format);
2291 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2293 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2294 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2297 gtk_widget_destroy (dialog);
2304 create_stream_for_uri (const gchar* uri)
2309 TnyStream *result = NULL;
2311 GnomeVFSHandle *handle = NULL;
2312 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2313 if (test == GNOME_VFS_OK) {
2314 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2315 /* Streams over OBEX (Bluetooth) are not seekable but
2316 * we expect them to be (we might need to read them
2317 * several times). So if this is a Bluetooth URI just
2318 * read the whole file into memory (this is not a fast
2319 * protocol so we can assume that these files are not
2320 * going to be very big) */
2321 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2322 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2323 TnyStream *memstream = tny_camel_mem_stream_new ();
2324 tny_stream_write_to_stream (vfssstream, memstream);
2325 g_object_unref (vfssstream);
2328 result = vfssstream;
2336 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2339 ModestMsgEditWindowPrivate *priv;
2340 GtkWidget *dialog = NULL;
2342 GSList *uris = NULL;
2343 GSList *uri_node = NULL;
2345 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2347 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2348 _("mcen_ia_select_inline_image_title"),
2349 (GtkWindow *) window,
2350 GTK_FILE_CHOOSER_ACTION_OPEN);
2351 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2353 #ifdef MODEST_TOOLKIT_HILDON2
2354 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2357 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2358 GTK_WINDOW (dialog), GTK_WINDOW (window));
2360 response = gtk_dialog_run (GTK_DIALOG (dialog));
2362 case GTK_RESPONSE_OK:
2364 gchar *current_folder;
2365 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2366 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2367 if (current_folder && current_folder != '\0') {
2369 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2370 current_folder, &err);
2372 g_debug ("Error storing latest used folder: %s", err->message);
2376 g_free (current_folder);
2382 gtk_widget_destroy (dialog);
2384 g_object_ref (window);
2385 /* The operation could take some time so allow the dialog to be closed */
2386 while (gtk_events_pending ())
2387 gtk_main_iteration ();
2389 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2391 GnomeVFSHandle *handle = NULL;
2392 GnomeVFSResult result;
2393 GtkTextIter position;
2394 GtkTextMark *insert_mark;
2396 uri = (const gchar *) uri_node->data;
2397 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2398 if (result == GNOME_VFS_OK) {
2400 GnomeVFSFileInfo *info;
2401 gchar *filename, *basename, *escaped_filename;
2402 TnyMimePart *mime_part;
2404 const gchar *mime_type = NULL;
2405 GnomeVFSURI *vfs_uri;
2406 guint64 stream_size;
2408 gnome_vfs_close (handle);
2409 vfs_uri = gnome_vfs_uri_new (uri);
2411 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2412 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2413 g_free (escaped_filename);
2414 gnome_vfs_uri_unref (vfs_uri);
2415 info = gnome_vfs_file_info_new ();
2417 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2418 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2420 mime_type = gnome_vfs_file_info_get_mime_type (info);
2422 mime_part = tny_platform_factory_new_mime_part
2423 (modest_runtime_get_platform_factory ());
2425 TnyStream *stream = create_stream_for_uri (uri);
2427 if (stream == NULL) {
2429 modest_platform_information_banner (NULL, NULL,
2430 _FM_OPENING_NOT_ALLOWED);
2432 g_object_unref (mime_part);
2433 gnome_vfs_file_info_unref (info);
2437 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2439 content_id = g_strdup_printf ("%d", priv->next_cid);
2440 tny_mime_part_set_content_id (mime_part, content_id);
2441 g_free (content_id);
2444 basename = g_path_get_basename (filename);
2445 tny_mime_part_set_filename (mime_part, basename);
2448 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2450 if (pixbuf != NULL) {
2451 priv->images_size += stream_size;
2452 priv->images_count ++;
2453 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2454 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2455 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2456 tny_mime_part_get_content_id (mime_part), pixbuf);
2457 g_object_unref (pixbuf);
2459 tny_list_prepend (priv->images, (GObject *) mime_part);
2460 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2462 modest_platform_information_banner (NULL, NULL,
2463 _("mail_ib_file_operation_failed"));
2467 g_object_unref (mime_part);
2468 gnome_vfs_file_info_unref (info);
2472 g_object_unref (window);
2476 on_attach_file_response (GtkDialog *dialog,
2480 GSList *uris = NULL;
2482 GnomeVFSFileSize total_size, allowed_size;
2483 ModestMsgEditWindow *window;
2484 ModestMsgEditWindowPrivate *priv;
2489 case GTK_RESPONSE_OK:
2491 gchar *current_folder;
2493 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2494 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2495 if (current_folder && current_folder != '\0') {
2497 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2498 current_folder, &err);
2500 g_debug ("Error storing latest used folder: %s", err->message);
2504 g_free (current_folder);
2511 window = MODEST_MSG_EDIT_WINDOW (user_data);
2512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2514 /* allowed size is the maximum size - what's already there */
2515 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2516 &att_num, &att_size);
2517 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2520 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2522 const gchar *uri = (const gchar *) uri_node->data;
2525 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2527 if (total_size > allowed_size) {
2528 g_debug ("%s: total size: %u",
2529 __FUNCTION__, (unsigned int)total_size);
2532 allowed_size -= total_size;
2534 g_slist_foreach (uris, (GFunc) g_free, NULL);
2535 g_slist_free (uris);
2537 gtk_widget_destroy (GTK_WIDGET (dialog));
2541 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2543 GtkWidget *dialog = NULL;
2544 ModestMsgEditWindowPrivate *priv;
2547 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2551 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2554 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2555 _("mcen_ia_select_attachment_title"),
2556 (GtkWindow *) window,
2557 GTK_FILE_CHOOSER_ACTION_OPEN);
2558 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2559 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2560 if (conf_folder && conf_folder[0] != '\0') {
2561 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2564 /* Set the default folder to documents folder */
2565 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2566 #ifdef MODEST_TOOLKIT_HILDON2
2569 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2570 ".documents", NULL);
2573 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2574 g_free (docs_folder);
2576 g_free (conf_folder);
2577 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2578 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2579 GTK_WINDOW (dialog), GTK_WINDOW (window));
2581 /* Connect to response & show */
2582 g_signal_connect (dialog, "response",
2583 G_CALLBACK (on_attach_file_response), window);
2584 gtk_widget_show (dialog);
2589 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2591 GnomeVFSFileSize allowed_size)
2594 GnomeVFSHandle *handle = NULL;
2595 ModestMsgEditWindowPrivate *priv;
2596 GnomeVFSResult result;
2597 GnomeVFSFileSize size = 0;
2598 g_return_val_if_fail (window, 0);
2599 g_return_val_if_fail (uri, 0);
2601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2603 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2604 if (result == GNOME_VFS_OK) {
2605 TnyMimePart *mime_part;
2607 const gchar *mime_type = NULL;
2609 gchar *escaped_filename;
2612 GnomeVFSFileInfo *info;
2613 GnomeVFSURI *vfs_uri;
2615 gnome_vfs_close (handle);
2616 vfs_uri = gnome_vfs_uri_new (uri);
2619 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2620 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2621 g_free (escaped_filename);
2622 gnome_vfs_uri_unref (vfs_uri);
2624 info = gnome_vfs_file_info_new ();
2626 if (gnome_vfs_get_file_info (uri,
2628 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2630 mime_type = gnome_vfs_file_info_get_mime_type (info);
2631 mime_part = tny_platform_factory_new_mime_part
2632 (modest_runtime_get_platform_factory ());
2634 /* try to get the attachment's size; this may fail for weird
2635 * file systems, like obex, upnp... */
2636 if (allowed_size != 0 &&
2637 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2639 if (size > allowed_size) {
2640 modest_platform_information_banner (NULL, NULL,
2641 _("mail_ib_error_attachment_size"));
2646 g_debug ("%s: could not get attachment size", __FUNCTION__);
2648 stream = create_stream_for_uri (uri);
2650 if (stream == NULL) {
2652 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2654 g_object_unref (mime_part);
2656 gnome_vfs_file_info_unref (info);
2660 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2661 g_object_unref (stream);
2663 content_id = g_strdup_printf ("%d", priv->next_cid);
2664 tny_mime_part_set_content_id (mime_part, content_id);
2665 g_free (content_id);
2668 basename = g_path_get_basename (filename);
2669 tny_mime_part_set_filename (mime_part, basename);
2672 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2673 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2675 info->size == 0, info->size);
2676 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2677 gtk_widget_show_all (priv->attachments_caption);
2678 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2680 g_object_unref (mime_part);
2681 gnome_vfs_file_info_unref (info);
2688 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2691 ModestMsgEditWindowPrivate *priv;
2694 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2695 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2697 if (att_list == NULL) {
2698 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2699 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2700 g_object_unref (att_list);
2704 g_object_ref (att_list);
2707 if (tny_list_get_length (att_list) == 0) {
2708 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2710 gboolean dialog_response;
2711 gchar *message = NULL;
2712 gchar *filename = NULL;
2714 if (tny_list_get_length (att_list) == 1) {
2716 iter = tny_list_create_iterator (att_list);
2717 part = (TnyMimePart *) tny_iterator_get_current (iter);
2718 g_object_unref (iter);
2719 if (TNY_IS_MSG (part)) {
2720 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2722 filename = tny_header_dup_subject (header);
2723 g_object_unref (header);
2725 if (filename == NULL) {
2726 filename = g_strdup (_("mail_va_no_subject"));
2729 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2731 g_object_unref (part);
2733 filename = g_strdup ("");
2735 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2736 "emev_nc_delete_attachments",
2737 tny_list_get_length (att_list)), filename);
2740 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2744 if (dialog_response != GTK_RESPONSE_OK) {
2745 g_object_unref (att_list);
2749 for (iter = tny_list_create_iterator (att_list);
2750 !tny_iterator_is_done (iter);
2751 tny_iterator_next (iter)) {
2752 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2753 const gchar *att_id;
2754 tny_list_remove (priv->attachments, (GObject *) mime_part);
2756 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2758 if (tny_list_get_length (priv->attachments) == 0)
2759 gtk_widget_hide (priv->attachments_caption);
2760 att_id = tny_mime_part_get_content_id (mime_part);
2762 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2764 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2765 g_object_unref (mime_part);
2767 g_object_unref (iter);
2770 g_object_unref (att_list);
2772 /* if the last attachment has been removed, focus the Subject: field */
2773 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2774 gtk_widget_grab_focus (priv->subject_field);
2778 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2781 ModestMsgEditWindowPrivate *priv;
2784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2786 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2788 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2790 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2794 font_size_clicked (GtkToolButton *button,
2795 ModestMsgEditWindow *window)
2797 #ifdef MODEST_TOOLKIT_HILDON2
2798 ModestMsgEditWindowPrivate *priv;
2799 GtkWidget *selector, *dialog;
2801 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2803 selector = hildon_touch_selector_new ();
2804 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2805 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2807 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2808 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2809 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2811 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2815 WPTextBufferFormat format;
2817 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2819 memset (&format, 0, sizeof (format));
2820 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2822 format.cs.font_size = TRUE;
2823 format.cs.text_position = TRUE;
2824 format.cs.font = TRUE;
2825 format.font_size = new_index;
2826 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2828 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2829 GINT_TO_POINTER (new_index)))
2830 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2832 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2833 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2834 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2835 size_text, "</span>", NULL);
2837 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2841 gtk_widget_destroy (dialog);
2843 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2848 font_face_clicked (GtkToolButton *button,
2849 ModestMsgEditWindow *window)
2851 #ifdef MODEST_TOOLKIT_HILDON2
2852 ModestMsgEditWindowPrivate *priv;
2853 GtkWidget *selector, *dialog;
2854 GtkCellRenderer *renderer;
2856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2858 selector = hildon_touch_selector_new ();
2859 renderer = gtk_cell_renderer_text_new ();
2860 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2861 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2862 renderer, "family", 0, "text", 0, NULL);
2863 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2865 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2866 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2867 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2869 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2870 gint new_font_index;
2874 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2875 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2876 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2880 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2882 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2883 GINT_TO_POINTER(new_font_index)))
2884 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2886 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2887 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2889 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2893 gtk_tree_path_free (path);
2896 gtk_widget_destroy (dialog);
2898 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2903 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2906 ModestMsgEditWindowPrivate *priv = NULL;
2907 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2910 if (!priv->update_caption_visibility)
2913 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2915 gtk_widget_show (priv->cc_caption);
2917 gtk_widget_hide (priv->cc_caption);
2919 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2923 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2926 ModestMsgEditWindowPrivate *priv = NULL;
2927 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2930 if (!priv->update_caption_visibility)
2933 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2935 gtk_widget_show (priv->bcc_caption);
2937 gtk_widget_hide (priv->bcc_caption);
2939 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2943 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2944 ModestRecptEditor *editor)
2946 ModestMsgEditWindowPrivate *priv;
2948 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2949 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2951 /* we check for low-mem; in that case, show a warning, and don't allow
2952 * for the addressbook
2954 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959 if (editor == NULL) {
2960 GtkWidget *view_focus, *parent;
2961 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2963 /* This code should be kept in sync with ModestRecptEditor. The
2964 textview inside the recpt editor is the one that really gets the
2965 focus. As it's inside a scrolled window, and this one inside the
2966 hbox recpt editor inherits from, we'll need to go up in the
2967 hierarchy to know if the text view is part of the recpt editor
2968 or if it's a different text entry */
2969 parent = gtk_widget_get_parent (view_focus);
2970 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2971 editor = MODEST_RECPT_EDITOR (parent);
2974 editor = MODEST_RECPT_EDITOR (priv->to_field);
2977 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2981 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2983 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2985 modest_msg_edit_window_open_addressbook (window, NULL);
2989 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2990 gboolean show_toolbar)
2992 ModestWindowPrivate *parent_priv;
2993 ModestMsgEditWindowPrivate *priv;
2995 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2996 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2997 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2999 /* We can not just use the code of
3000 modest_msg_edit_window_setup_toolbar because it has a
3001 mixture of both initialization and creation code. */
3003 gint current_format;
3004 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3005 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3006 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3007 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3009 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3012 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3017 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3018 TnyHeaderFlags priority_flags)
3020 ModestMsgEditWindowPrivate *priv;
3021 ModestWindowPrivate *parent_priv;
3023 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3026 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3028 if (priv->priority_flags != priority_flags) {
3029 GtkAction *priority_action = NULL;
3031 priv->priority_flags = priority_flags;
3033 switch (priority_flags) {
3034 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3035 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3036 MODEST_HEADER_ICON_HIGH,
3037 #ifdef MODEST_TOOLKIT_HILDON2
3038 HILDON_ICON_SIZE_SMALL
3040 GTK_ICON_SIZE_BUTTON
3043 gtk_widget_show (priv->priority_icon);
3044 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3045 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3047 case TNY_HEADER_FLAG_LOW_PRIORITY:
3048 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3049 MODEST_HEADER_ICON_LOW,
3050 #ifdef MODEST_TOOLKIT_HILDON2
3051 HILDON_ICON_SIZE_SMALL
3053 GTK_ICON_SIZE_BUTTON
3056 gtk_widget_show (priv->priority_icon);
3057 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3058 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3061 gtk_widget_hide (priv->priority_icon);
3062 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3063 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3066 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3067 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3069 gtk_widget_queue_resize (priv->subject_box);
3073 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3076 ModestMsgEditWindowPrivate *priv;
3077 ModestWindowPrivate *parent_priv;
3078 gint current_format;
3080 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3082 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3085 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3086 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3088 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3090 if (current_format != file_format) {
3091 switch (file_format) {
3092 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3093 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3094 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3095 if (parent_priv->toolbar)
3096 gtk_widget_show (parent_priv->toolbar);
3098 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3101 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3102 if (response == GTK_RESPONSE_OK) {
3103 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3104 if (parent_priv->toolbar)
3105 gtk_widget_hide (parent_priv->toolbar);
3107 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3108 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3113 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3114 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3115 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3120 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3122 #ifdef MODEST_TOOLKIT_HILDON2
3124 ModestMsgEditWindowPrivate *priv;
3125 WPTextBufferFormat oldfmt, fmt;
3126 gint old_position = 0;
3130 GdkColor *color = NULL;
3131 gboolean bold, bold_set, italic, italic_set;
3132 gboolean underline, underline_set;
3133 gboolean strikethrough, strikethrough_set;
3134 gboolean position_set;
3135 gboolean font_size_set, font_set, color_set;
3138 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3139 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3141 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3142 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3143 GTK_WINDOW(dialog), GTK_WINDOW (window));
3145 /* First we get the currently selected font information */
3146 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3148 switch (oldfmt.text_position) {
3149 case TEXT_POSITION_NORMAL:
3152 case TEXT_POSITION_SUPERSCRIPT:
3160 g_object_set (G_OBJECT (dialog),
3161 "bold", oldfmt.bold != FALSE,
3162 "bold-set", !oldfmt.cs.bold,
3163 "underline", oldfmt.underline != FALSE,
3164 "underline-set", !oldfmt.cs.underline,
3165 "italic", oldfmt.italic != FALSE,
3166 "italic-set", !oldfmt.cs.italic,
3167 "strikethrough", oldfmt.strikethrough != FALSE,
3168 "strikethrough-set", !oldfmt.cs.strikethrough,
3169 "color", &oldfmt.color,
3170 "color-set", !oldfmt.cs.color,
3171 "size", wp_font_size[oldfmt.font_size],
3172 "size-set", !oldfmt.cs.font_size,
3173 "position", old_position,
3174 "position-set", !oldfmt.cs.text_position,
3175 "family", wp_get_font_name (oldfmt.font),
3176 "family-set", !oldfmt.cs.font,
3179 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3180 GTK_WINDOW (dialog), GTK_WINDOW (window));
3181 gtk_widget_show_all (dialog);
3182 priv->font_dialog = dialog;
3183 response = gtk_dialog_run (GTK_DIALOG (dialog));
3184 priv->font_dialog = NULL;
3185 if (response == GTK_RESPONSE_OK) {
3187 g_object_get( dialog,
3189 "bold-set", &bold_set,
3190 "underline", &underline,
3191 "underline-set", &underline_set,
3193 "italic-set", &italic_set,
3194 "strikethrough", &strikethrough,
3195 "strikethrough-set", &strikethrough_set,
3197 "color-set", &color_set,
3199 "size-set", &font_size_set,
3200 "family", &font_name,
3201 "family-set", &font_set,
3202 "position", &position,
3203 "position-set", &position_set,
3208 if (response == GTK_RESPONSE_OK) {
3209 memset(&fmt, 0, sizeof(fmt));
3215 fmt.italic = italic;
3216 fmt.cs.italic = TRUE;
3218 if (underline_set) {
3219 fmt.underline = underline;
3220 fmt.cs.underline = TRUE;
3222 if (strikethrough_set) {
3223 fmt.strikethrough = strikethrough;
3224 fmt.cs.strikethrough = TRUE;
3229 ? TEXT_POSITION_NORMAL
3230 : ( ( position == 1 )
3231 ? TEXT_POSITION_SUPERSCRIPT
3232 : TEXT_POSITION_SUBSCRIPT );
3233 fmt.cs.text_position = TRUE;
3234 fmt.font_size = oldfmt.font_size;
3238 fmt.cs.color = TRUE;
3241 fmt.font = wp_get_font_index(font_name,
3246 if (font_size_set) {
3247 fmt.cs.font_size = TRUE;
3248 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3250 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3251 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3253 gtk_widget_destroy (dialog);
3255 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3260 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv;
3263 ModestWindowPrivate *parent_priv;
3264 gboolean was_rich_text, is_rich_text;
3266 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3268 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3270 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3272 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3274 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3276 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3278 gtk_widget_show (parent_priv->toolbar);
3280 gtk_widget_hide (parent_priv->toolbar);
3283 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3284 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3288 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3290 ModestMsgEditWindowPrivate *priv;
3292 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3295 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3297 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3298 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3303 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3305 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3307 priv->can_undo = can_undo;
3311 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3313 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3315 priv->can_redo = can_redo;
3319 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3321 ModestMsgEditWindowPrivate *priv;
3322 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3323 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3325 return priv->can_undo;
3329 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3331 ModestMsgEditWindowPrivate *priv;
3332 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3333 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3335 return priv->can_redo;
3340 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3343 GtkTextIter match_start, match_end;
3345 if (image_id == NULL)
3348 gtk_text_buffer_get_start_iter (buffer, &iter);
3350 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3351 GSList *tags = gtk_text_iter_get_tags (&match_start);
3353 for (node = tags; node != NULL; node = g_slist_next (node)) {
3354 GtkTextTag *tag = (GtkTextTag *) node->data;
3355 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3356 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3357 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3359 offset = gtk_text_iter_get_offset (&match_start);
3360 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3361 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3365 gtk_text_iter_forward_char (&iter);
3370 message_is_empty (ModestMsgEditWindow *window)
3372 ModestMsgEditWindowPrivate *priv = NULL;
3374 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3375 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3377 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3378 * so we can ignore markup.
3380 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3383 count = gtk_text_buffer_get_char_count (buf);
3389 msg_body_focus (GtkWidget *focus,
3390 GdkEventFocus *event,
3394 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3395 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3396 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3401 recpt_field_changed (GtkTextBuffer *buffer,
3402 ModestMsgEditWindow *editor)
3404 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3405 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3409 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3411 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3412 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3416 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3419 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3420 GtkTextBuffer *buffer;
3422 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3423 gtk_text_buffer_set_modified (buffer, modified);
3424 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3425 gtk_text_buffer_set_modified (buffer, modified);
3426 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3427 gtk_text_buffer_set_modified (buffer, modified);
3428 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3432 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3434 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3435 const char *account_name;
3436 GtkTextBuffer *buffer;
3438 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3439 if (gtk_text_buffer_get_modified (buffer))
3441 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3442 if (gtk_text_buffer_get_modified (buffer))
3444 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3445 if (gtk_text_buffer_get_modified (buffer))
3447 if (gtk_text_buffer_get_modified (priv->text_buffer))
3450 account_name = modest_selector_get_active_id (priv->from_field);
3451 if (priv->original_mailbox) {
3452 if (!account_name || strcmp (account_name, priv->original_mailbox))
3454 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3465 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3467 ModestMsgEditWindowPrivate *priv = NULL;
3468 GSList *address_list = NULL;
3470 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3473 /* check if there's no recipient added */
3474 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3475 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3476 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3477 /* no recipient contents, then select contacts */
3478 modest_msg_edit_window_open_addressbook (window, NULL);
3483 g_object_ref (window);
3484 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3485 (add_to_addressbook) ? &address_list : NULL)) {
3486 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3487 g_object_unref (window);
3490 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3491 (add_to_addressbook) ? &address_list : NULL)) {
3492 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3493 g_object_unref (window);
3496 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3497 (add_to_addressbook) ? &address_list : NULL)) {
3498 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3499 g_object_unref (window);
3503 /* Add contacts to address book */
3504 if (add_to_addressbook && address_list)
3505 modest_address_book_add_address_list (address_list);
3507 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3508 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3509 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3510 g_object_unref (window);
3517 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3519 GSList *recipients = NULL;
3520 ModestMsgEditWindowPrivate *priv;
3521 gchar *joined, *after_remove, *to, *cc, *bcc;
3523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3525 /* First of all check names */
3526 if (!modest_msg_edit_window_check_names (self, FALSE))
3529 if (!modest_msg_edit_window_has_pending_addresses (self))
3532 /* Don't add the from obviously */
3533 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3534 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3535 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3537 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3542 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3545 recipients = modest_text_utils_split_addresses_list (after_remove);
3546 g_free (after_remove);
3549 /* Offer the user to add recipients to the address book */
3550 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3551 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3556 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3557 ModestMsgEditWindow *window)
3559 modest_msg_edit_window_offer_attach_file (window);
3563 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3565 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3567 return priv->clipboard_text;
3571 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3573 ModestMsgEditWindow *window)
3575 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3576 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3579 /* It could happen that the window was already closed */
3580 if (!GTK_WIDGET_VISIBLE (window))
3583 g_object_ref (window);
3584 text = gtk_clipboard_wait_for_text (selection_clipboard);
3586 if (priv->clipboard_text != NULL) {
3587 g_free (priv->clipboard_text);
3589 priv->clipboard_text = text;
3591 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3593 g_object_unref (window);
3596 static gboolean clipboard_owner_change_idle (gpointer userdata)
3598 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3599 ModestMsgEditWindowPrivate *priv;
3601 gdk_threads_enter ();
3602 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3603 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3605 priv->clipboard_owner_idle = 0;
3606 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3607 gdk_threads_leave ();
3613 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3615 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3616 if (priv->clipboard_owner_idle == 0) {
3617 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3618 clipboard_owner_change_idle,
3619 g_object_ref (window),
3625 subject_field_move_cursor (GtkEntry *entry,
3626 GtkMovementStep step,
3631 /* It could happen that the window was already closed */
3632 if (!GTK_WIDGET_VISIBLE (window))
3635 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3639 update_window_title (ModestMsgEditWindow *window)
3641 ModestMsgEditWindowPrivate *priv = NULL;
3642 const gchar *subject;
3644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3645 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3646 if (subject == NULL || subject[0] == '\0')
3647 subject = _("mail_va_new_email");
3649 modest_window_set_title (MODEST_WINDOW (window), subject);
3655 body_insert_text (GtkTextBuffer *buffer,
3656 GtkTextIter *location,
3659 ModestMsgEditWindow *window)
3661 GtkTextIter end_iter;
3668 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3670 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3672 offset = gtk_text_iter_get_offset (&end_iter);
3673 line = gtk_text_iter_get_line (&end_iter);
3677 while (text_offset < text + len) {
3678 if (*text_offset == '\n')
3680 if (text_lines + line >= MAX_BODY_LINES) {
3681 len = text_offset - text;
3687 utf8_len = g_utf8_strlen (text, len);
3689 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3690 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3691 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3696 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3698 /* Prevent endless recursion */
3699 result = g_strndup (text, utf8_end - text);
3700 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3701 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3702 (gpointer) result, (gpointer) (utf8_end - text),
3704 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3708 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3709 if (priv->max_chars_banner == NULL) {
3710 #ifdef MODEST_TOOLKIT_HILDON2
3711 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3712 _CS_MAXIMUM_CHARACTERS_REACHED);
3713 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3720 subject_field_changed (GtkEditable *editable,
3721 ModestMsgEditWindow *window)
3723 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3724 update_window_title (window);
3725 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3726 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3727 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3730 subject_field_insert_text (GtkEditable *editable,
3732 gint new_text_length,
3734 ModestMsgEditWindow *window)
3736 GString *result = g_string_new ("");
3738 gint result_len = 0;
3739 const gchar *entry_text = NULL;
3742 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3743 old_length = g_utf8_strlen (entry_text, -1);
3745 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3746 gunichar c = g_utf8_get_char_validated (current, 8);
3747 /* Invalid unichar, stop */
3753 result = g_string_append_unichar (result, c);
3757 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3758 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3761 /* Prevent endless recursion */
3762 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3763 g_signal_emit_by_name (editable, "insert-text",
3764 (gpointer) result->str, (gpointer) result->len,
3765 (gpointer) position, (gpointer) window);
3766 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3770 if (result_len + old_length > 1000) {
3771 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3772 _CS_MAXIMUM_CHARACTERS_REACHED);
3774 g_string_free (result, TRUE);
3778 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
3781 ModestMsgEditWindowPrivate *priv = NULL;
3783 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3786 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
3789 gtk_widget_show_all (priv->isearch_toolbar);
3790 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
3792 gtk_widget_hide_all (priv->isearch_toolbar);
3793 gtk_widget_grab_focus (priv->msg_body);
3798 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3800 GtkTextIter *match_start,
3801 GtkTextIter *match_end)
3803 GtkTextIter end_iter;
3804 gchar *str_casefold;
3807 gchar *range_casefold;
3810 gboolean result = FALSE;
3817 gtk_text_iter_forward_to_end (&end_iter);
3819 str_casefold = g_utf8_casefold (str, -1);
3820 str_chars_n = strlen (str);
3822 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3823 range_casefold = g_utf8_casefold (range_text, -1);
3824 range_chars_n = strlen (range_casefold);
3826 if (range_chars_n < str_chars_n) {
3827 g_free (str_casefold);
3828 g_free (range_text);
3829 g_free (range_casefold);
3833 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3834 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3835 if (!g_utf8_collate (range_subtext, str_casefold)) {
3836 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3838 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3839 match_start, match_end, NULL)) {
3840 g_debug ("Matched string with collate, but not matched in model");
3842 g_free (found_text);
3844 g_free (range_subtext);
3848 g_free (str_casefold);
3849 g_free (range_text);
3850 g_free (range_casefold);
3857 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
3858 ModestMsgEditWindow *window)
3860 const gchar *current_search = NULL;
3861 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3863 GtkTextIter selection_start, selection_end;
3864 GtkTextIter match_start, match_end;
3865 gboolean continue_search = FALSE;
3867 if (message_is_empty (window)) {
3868 g_free (priv->last_search);
3869 priv->last_search = NULL;
3870 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3874 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
3875 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3876 g_free (priv->last_search);
3877 priv->last_search = NULL;
3878 /* Information banner about empty search */
3879 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
3883 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3884 continue_search = TRUE;
3886 g_free (priv->last_search);
3887 priv->last_search = g_strdup (current_search);
3890 if (continue_search) {
3891 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3892 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3893 &match_start, &match_end);
3895 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
3897 GtkTextIter buffer_start;
3898 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3899 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3900 &match_start, &match_end);
3902 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
3905 /* Mark as selected the string found in search */
3907 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3908 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3909 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3911 g_free (priv->last_search);
3912 priv->last_search = NULL;
3917 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3919 ModestMsgEditWindowPrivate *priv;
3921 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3926 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3929 ModestMsgEditWindowPrivate *priv;
3931 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3936 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
3937 ModestMsgEditWindow *window)
3939 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
3943 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3946 ModestMsgEditWindowPrivate *priv;
3947 TnyHeader *header = NULL;
3949 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3950 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3952 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3954 if (priv->draft_msg != NULL) {
3955 g_object_unref (priv->draft_msg);
3958 if (draft != NULL) {
3959 g_object_ref (draft);
3960 header = tny_msg_get_header (draft);
3961 if (priv->msg_uid) {
3962 g_free (priv->msg_uid);
3963 priv->msg_uid = NULL;
3965 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3968 priv->draft_msg = draft;
3972 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3973 GtkTextIter *start, GtkTextIter *end,
3976 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3977 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3980 if (tag == NULL) return;
3981 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3982 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3983 replace_with_images (window, priv->images);
3988 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3991 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3993 g_return_if_fail (TNY_IS_MIME_PART (part));
3994 tny_list_prepend (priv->attachments, (GObject *) part);
3995 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3996 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3997 gtk_widget_show_all (priv->attachments_caption);
3998 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4002 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4004 ModestMsgEditWindowPrivate *priv;
4006 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4009 return priv->msg_uid;
4013 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4014 ModestMsgEditWindowWidgetType widget_type)
4016 ModestMsgEditWindowPrivate *priv;
4018 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4021 switch (widget_type) {
4022 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4023 return priv->msg_body;
4025 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4026 return priv->to_field;
4028 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4029 return priv->cc_field;
4031 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4032 return priv->bcc_field;
4034 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4035 return priv->subject_field;
4037 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4038 return priv->attachments_view;
4046 remove_tags (WPTextBuffer *buffer)
4048 GtkTextIter start, end;
4050 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4051 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4053 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4057 on_account_removed (TnyAccountStore *account_store,
4058 TnyAccount *account,
4061 /* Do nothing if it's a store account, because we use the
4062 transport to send the messages */
4063 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4064 const gchar *parent_acc = NULL;
4065 const gchar *our_acc = NULL;
4067 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4068 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4069 /* Close this window if I'm showing a message of the removed account */
4070 if (strcmp (parent_acc, our_acc) == 0)
4071 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4076 update_signature (ModestMsgEditWindow *self,
4077 const gchar *old_account,
4078 const gchar *new_account)
4080 ModestMsgEditWindowPrivate *priv;
4081 gboolean has_old_signature, has_new_signature;
4083 ModestAccountMgr *mgr;
4086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4088 gtk_text_buffer_begin_user_action (priv->text_buffer);
4090 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4091 mgr = modest_runtime_get_account_mgr ();
4095 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4096 if (has_old_signature) {
4097 GtkTextIter match_start, match_end;
4099 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4100 seems that the search has some problems
4101 with the blank space at the end */
4102 if (gtk_text_iter_forward_search (&iter, "--",
4103 GTK_TEXT_SEARCH_TEXT_ONLY,
4104 &match_start, NULL, NULL)) {
4105 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4106 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4108 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4109 &match_start, &match_end, NULL)) {
4113 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4118 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4119 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4120 if (has_new_signature) {
4123 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4124 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4126 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4128 WPTextBufferFormat *fmt;
4129 GdkColor style_color;
4130 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4131 gdk_color_parse ("grey", &style_color);
4133 fmt = g_new0 (WPTextBufferFormat, 1);
4134 fmt->color = style_color;
4135 fmt->cs.color = 0x1;
4136 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4140 g_free (full_signature);
4142 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4146 gtk_text_buffer_end_user_action (priv->text_buffer);
4149 static void update_branding (ModestMsgEditWindow *self,
4150 const gchar *new_account)
4152 ModestMsgEditWindowPrivate *priv;
4153 ModestAccountMgr *mgr;
4154 const GdkPixbuf *new_icon = NULL;
4155 gchar *new_label = NULL;
4156 gboolean show = FALSE;
4158 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4160 mgr = modest_runtime_get_account_mgr ();
4162 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4164 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4165 gtk_widget_show (priv->brand_icon);
4168 gtk_widget_hide (priv->brand_icon);
4171 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4172 gtk_widget_show (priv->brand_label);
4176 gtk_widget_hide (priv->brand_label);
4180 gtk_widget_show (priv->brand_container);
4182 gtk_widget_hide (priv->brand_container);
4186 from_field_changed (GtkWidget *button,
4187 ModestMsgEditWindow *self)
4189 ModestMsgEditWindowPrivate *priv;
4190 gchar *old_account, *new_account;
4192 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4194 old_account = priv->last_from_account;
4195 new_account = modest_selector_get_active_id (priv->from_field);
4198 g_warning ("%s, could not get the new account", __FUNCTION__);
4202 /* If the From is the same do nothing */
4203 if (old_account && new_account && !strcmp (old_account, new_account))
4206 priv->last_from_account = new_account;
4208 update_signature (self, old_account, new_account);
4209 update_branding (self, new_account);
4213 typedef struct _MessageSettingsHelper {
4214 ModestMsgEditWindow *window;
4215 GSList *priority_group;
4216 GSList *format_group;
4217 GtkToggleButton *current_priority;
4218 GtkToggleButton *current_format;
4219 } MessageSettingsHelper;
4221 #ifdef MODEST_TOOLKIT_HILDON2
4223 on_priority_toggle (GtkToggleButton *button,
4224 MessageSettingsHelper *helper)
4227 ModestMsgEditWindowPrivate *priv;
4229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4230 if (gtk_toggle_button_get_active (button)) {
4232 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4233 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4234 if ((node_button != button) &&
4235 gtk_toggle_button_get_active (node_button)) {
4236 gtk_toggle_button_set_active (node_button, FALSE);
4239 helper->current_priority = button;
4241 gboolean found = FALSE;
4242 /* If no one is active, activate it again */
4243 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4244 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4245 if (gtk_toggle_button_get_active (node_button)) {
4251 gtk_toggle_button_set_active (button, TRUE);
4257 on_format_toggle (GtkToggleButton *button,
4258 MessageSettingsHelper *helper)
4261 ModestMsgEditWindowPrivate *priv;
4263 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4264 if (gtk_toggle_button_get_active (button)) {
4266 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4267 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4268 if ((node_button != button) &&
4269 gtk_toggle_button_get_active (node_button)) {
4270 gtk_toggle_button_set_active (node_button, FALSE);
4273 helper->current_format = button;
4275 gboolean found = FALSE;
4276 /* If no one is active, activate it again */
4277 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4278 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4279 if (gtk_toggle_button_get_active (node_button)) {
4285 gtk_toggle_button_set_active (button, TRUE);
4293 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4295 #ifdef MODEST_TOOLKIT_HILDON2
4299 GtkWidget *priority_hbox;
4300 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4301 GtkWidget *captioned;
4302 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4303 GtkWidget *format_hbox;
4304 GtkWidget *html_toggle, *text_toggle;
4305 ModestMsgEditWindowPrivate *priv;
4306 MessageSettingsHelper helper = {0,};
4308 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4309 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4310 helper.window = window;
4311 helper.priority_group = NULL;
4312 helper.format_group = NULL;
4314 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4315 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4317 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4318 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4319 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4320 vbox = gtk_vbox_new (FALSE, 0);
4321 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4322 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4323 gtk_container_add (GTK_CONTAINER (align), vbox);
4324 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4325 gtk_widget_show (align);
4326 gtk_widget_show (vbox);
4328 /* Priority toggles */
4329 priority_hbox = gtk_hbox_new (TRUE, 0);
4330 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4331 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4332 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4333 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4334 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4335 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4336 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4337 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4338 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4339 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4340 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4341 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4342 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4343 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4344 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4345 gtk_widget_show_all (priority_hbox);
4346 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4347 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4348 gtk_widget_show (captioned);
4349 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4351 /* format toggles */
4352 format_hbox = gtk_hbox_new (TRUE, 0);
4353 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4354 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4355 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4356 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4357 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4358 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4359 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4360 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4361 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4362 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4363 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4364 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4365 gtk_widget_show_all (format_hbox);
4366 gtk_widget_show (format_hbox);
4367 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4370 g_object_unref (title_sizegroup);
4371 g_object_unref (value_sizegroup);
4373 /* Set current values */
4374 switch (priv->priority_flags) {
4375 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4376 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4377 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4379 case TNY_HEADER_FLAG_LOW_PRIORITY:
4380 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4381 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4384 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4385 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4389 switch (modest_msg_edit_window_get_format (window)) {
4390 case MODEST_MSG_EDIT_FORMAT_TEXT:
4391 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4392 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4394 case MODEST_MSG_EDIT_FORMAT_HTML:
4396 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4397 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4401 /* Signal connects */
4402 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4403 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4404 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4405 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4406 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4408 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4409 GTK_WINDOW (dialog), GTK_WINDOW (window));
4411 /* Save settings if the user clicked on done */
4412 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4413 TnyHeaderFlags flags;
4414 ModestMsgEditFormat old_format, new_format;
4416 /* Set priority flags */
4417 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4418 if (priv->priority_flags != flags)
4419 modest_msg_edit_window_set_priority_flags (window, flags);
4421 /* Set edit format */
4422 old_format = modest_msg_edit_window_get_format (window);
4423 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4424 if (old_format != new_format) {
4425 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4426 modest_msg_edit_window_set_file_format (window, file_format);
4430 gtk_widget_destroy (dialog);
4431 g_slist_free (helper.priority_group);
4436 on_message_settings (GtkAction *action,
4437 ModestMsgEditWindow *window)
4439 modest_msg_edit_window_show_msg_settings_dialog (window);
4442 #ifdef MODEST_TOOLKIT_HILDON2
4444 on_cc_button_toggled (GtkWidget *button,
4445 ModestMsgEditWindow *window)
4447 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4449 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4450 modest_togglable_get_active (button));
4454 on_bcc_button_toggled (GtkWidget *button,
4455 ModestMsgEditWindow *window)
4457 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4459 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4460 modest_togglable_get_active (button));
4465 setup_menu (ModestMsgEditWindow *self)
4467 ModestMsgEditWindowPrivate *priv = NULL;
4469 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4473 /* Settings menu buttons */
4474 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4475 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4477 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4478 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4479 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4480 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4481 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4482 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4484 #ifdef MODEST_TOOLKIT_HILDON2
4485 priv->cc_button = hildon_check_button_new (0);
4486 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4487 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4489 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4490 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4491 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4493 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4494 _("mcen_me_editor_showbcc"));
4495 modest_togglable_set_active (priv->bcc_button,
4497 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4499 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4500 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4503 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4504 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4505 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4506 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4507 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4509 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4510 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4511 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4512 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4513 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4515 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4516 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4521 emit_open_addressbook (GtkButton *button,
4522 ModestRecptEditor *editor)
4524 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4528 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4529 const gchar *label, GtkWidget *control)
4531 GtkWidget *abook_button;
4534 GtkWidget *label_widget;
4536 box = gtk_hbox_new (FALSE, 0);
4538 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4539 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4541 #ifdef MODEST_TOOLKIT_HILDON2
4542 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4544 abook_button = gtk_button_new ();
4546 label_widget = gtk_label_new (label);
4547 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4548 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4550 gtk_container_add (GTK_CONTAINER (align), abook_button);
4551 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4552 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4553 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4554 if (title_size_group)
4555 gtk_size_group_add_widget (title_size_group, label_widget);
4556 if (value_size_group)
4557 gtk_size_group_add_widget (value_size_group, control);
4559 g_signal_connect (G_OBJECT (abook_button), "clicked",
4560 G_CALLBACK (emit_open_addressbook), control);
4566 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4568 ModestMsgEditWindowPrivate *priv = NULL;
4570 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4573 priv->max_chars_banner = NULL;
4577 has_pending_addresses (ModestRecptEditor *recpt_editor)
4579 const gchar *recipients = NULL;
4580 GSList *start_indexes = NULL, *end_indexes = NULL;
4581 GSList *current_start, *current_end;
4582 GtkTextBuffer *buffer;
4583 gint offset_delta = 0;
4585 gboolean has_recipients_to_add = FALSE;
4587 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4588 last_length = g_utf8_strlen (recipients, -1);
4589 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4594 current_start = start_indexes;
4595 current_end = end_indexes;
4596 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4598 while (current_start && !has_recipients_to_add) {
4600 gchar *start_ptr, *end_ptr;
4601 gint start_pos, end_pos;
4603 start_pos = (*((gint*) current_start->data)) + offset_delta;
4604 end_pos = (*((gint*) current_end->data)) + offset_delta;
4606 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4607 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4609 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4611 if (modest_text_utils_validate_recipient (address, NULL)) {
4612 if (!modest_address_book_has_address (address)) {
4613 has_recipients_to_add = TRUE;
4616 current_start = g_slist_next (current_start);
4617 current_end = g_slist_next (current_end);
4619 return has_recipients_to_add;
4623 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4625 ModestMsgEditWindowPrivate *priv = NULL;
4627 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4631 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4632 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4633 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))