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 <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
191 const gchar *label, GtkWidget *control);
192 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
193 static void DEBUG_BUFFER (WPTextBuffer *buffer)
197 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
199 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
200 while (!gtk_text_iter_is_end (&iter)) {
201 GString *output = g_string_new ("");
202 GSList *toggled_tags;
205 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
206 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
207 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
208 GtkTextTag *tag = (GtkTextTag *) node->data;
210 g_object_get (G_OBJECT (tag), "name", &name, NULL);
211 output = g_string_append (output, name);
212 g_string_append (output, " ");
214 output = g_string_append (output, "] OPENED [ ");
215 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
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, "]\n");
224 g_message ("%s", output->str);
225 g_string_free (output, TRUE);
226 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
228 g_message ("END BUFFER");
232 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
233 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
237 /* static gboolean */
238 /* on_key_pressed (GtkWidget *self, */
239 /* GdkEventKey *event, */
240 /* gpointer user_data); */
242 /* list my signals */
249 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
250 struct _ModestMsgEditWindowPrivate {
252 GtkWidget *header_box;
254 ModestPairList *from_field_protos;
255 GtkWidget *from_field;
256 gchar *last_from_account;
257 gchar *original_account_name;
262 gchar *original_mailbox;
266 GtkWidget *bcc_field;
267 GtkWidget *subject_field;
268 GtkWidget *attachments_view;
269 GtkWidget *priority_icon;
270 GtkWidget *subject_box;
271 GtkWidget *send_button;
273 GtkWidget *cc_caption;
274 GtkWidget *bcc_caption;
275 gboolean update_caption_visibility;
276 GtkWidget *attachments_caption;
278 GtkTextBuffer *text_buffer;
280 GtkWidget *font_size_toolitem;
281 GtkWidget *font_face_toolitem;
282 GtkWidget *font_color_button;
283 GtkWidget *font_color_toolitem;
284 GSList *font_items_group;
285 GtkTreeModel *faces_model;
286 gint current_face_index;
287 GtkWidget *font_tool_button_label;
288 GtkTreeModel *sizes_model;
289 gint current_size_index;
290 GtkWidget *size_tool_button_label;
292 GtkWidget *find_toolbar;
295 GtkWidget *font_dialog;
298 guint correct_scroll_idle;
299 guint scroll_drag_timeout_id;
303 TnyList *attachments;
308 TnyHeaderFlags priority_flags;
310 gboolean can_undo, can_redo;
311 gulong clipboard_change_handler_id;
312 gulong default_clipboard_change_handler_id;
313 gulong account_removed_handler_id;
314 guint clipboard_owner_idle;
315 gchar *clipboard_text;
324 GtkWidget *cc_button;
325 GtkWidget *bcc_button;
327 GtkWidget *max_chars_banner;
330 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
331 MODEST_TYPE_MSG_EDIT_WINDOW, \
332 ModestMsgEditWindowPrivate))
334 static GtkWindowClass *parent_class = NULL;
336 /* uncomment the following if you have defined any signals */
337 /* static guint signals[LAST_SIGNAL] = {0}; */
340 modest_msg_edit_window_get_type (void)
342 static GType my_type = 0;
344 static const GTypeInfo my_info = {
345 sizeof(ModestMsgEditWindowClass),
346 NULL, /* base init */
347 NULL, /* base finalize */
348 (GClassInitFunc) modest_msg_edit_window_class_init,
349 NULL, /* class finalize */
350 NULL, /* class data */
351 sizeof(ModestMsgEditWindow),
353 (GInstanceInitFunc) modest_msg_edit_window_init,
356 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
357 "ModestMsgEditWindow",
365 save_state (ModestWindow *self)
367 modest_widget_memory_save (modest_runtime_get_conf(),
368 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
373 restore_settings (ModestMsgEditWindow *self)
375 ModestConf *conf = NULL;
377 conf = modest_runtime_get_conf ();
379 /* Dim at start clipboard actions */
380 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
385 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
387 GObjectClass *gobject_class;
388 ModestWindowClass *modest_window_class;
389 gobject_class = (GObjectClass*) klass;
390 modest_window_class = (ModestWindowClass*) klass;
392 parent_class = g_type_class_peek_parent (klass);
393 gobject_class->finalize = modest_msg_edit_window_finalize;
395 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
396 modest_window_class->save_state_func = save_state;
397 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
399 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
403 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
405 ModestMsgEditWindowPrivate *priv;
406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
408 priv->msg_body = NULL;
409 priv->from_field = NULL;
410 priv->to_field = NULL;
411 priv->cc_field = NULL;
412 priv->bcc_field = NULL;
413 priv->subject_field = NULL;
414 priv->attachments = TNY_LIST (tny_simple_list_new ());
415 priv->images = TNY_LIST (tny_simple_list_new ());
416 priv->images_size = 0;
417 priv->images_count = 0;
420 priv->cc_caption = NULL;
421 priv->bcc_caption = NULL;
422 priv->update_caption_visibility = FALSE;
424 priv->priority_flags = 0;
426 priv->find_toolbar = NULL;
427 priv->last_search = NULL;
429 priv->draft_msg = NULL;
430 priv->outbox_msg = NULL;
431 priv->msg_uid = NULL;
433 priv->can_undo = FALSE;
434 priv->can_redo = FALSE;
435 priv->clipboard_change_handler_id = 0;
436 priv->default_clipboard_change_handler_id = 0;
437 priv->account_removed_handler_id = 0;
438 priv->clipboard_owner_idle = 0;
439 priv->clipboard_text = NULL;
442 priv->scroll_drag_timeout_id = 0;
443 priv->correct_scroll_idle = 0;
444 priv->last_upper = 0.0;
446 priv->font_dialog = NULL;
447 priv->app_menu = NULL;
449 priv->references = NULL;
450 priv->in_reply_to = NULL;
451 priv->max_chars_banner = NULL;
453 if (!is_wp_text_buffer_started) {
454 is_wp_text_buffer_started = TRUE;
455 wp_text_buffer_library_init ();
460 hildon_program_add_window (hildon_program_get_instance(),
465 multimailbox_get_default_mailbox (const gchar *account_name)
467 gchar *transport_account;
468 gchar *result = NULL;
470 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
472 TNY_ACCOUNT_TYPE_TRANSPORT);
473 if (transport_account) {
475 ModestProtocolRegistry *registry;
477 registry = modest_runtime_get_protocol_registry ();
479 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
480 MODEST_ACCOUNT_PROTO, TRUE);
482 ModestProtocol *protocol =
483 modest_protocol_registry_get_protocol_by_name (registry,
484 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
486 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
487 ModestPairList *pair_list;
489 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
492 ModestPair *pair = (ModestPair *) pair_list->data;
493 result = g_strdup ((const gchar *) pair->first);
494 modest_pair_list_free (pair_list);
505 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
507 static ModestPairList*
508 get_transports (void)
510 GSList *transports = NULL;
512 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
513 GSList *accounts = modest_account_mgr_account_names (account_mgr,
514 TRUE /* only enabled accounts. */);
516 GSList *cursor = accounts;
518 gchar *account_name = cursor->data;
521 gchar *transport_account;
522 gboolean multi_mailbox = FALSE;
523 ModestProtocol *protocol = NULL;
525 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
527 transport_account = modest_account_mgr_get_server_account_name
528 (modest_runtime_get_account_mgr (),
530 TNY_ACCOUNT_TYPE_TRANSPORT);
531 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
532 ModestPairList *pair_list;
533 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
536 transports = g_slist_concat (transports, pair_list);
537 multi_mailbox = TRUE;
542 if (!multi_mailbox) {
543 gchar *from_string = NULL;
545 from_string = modest_account_mgr_get_from_string (account_mgr,
547 if (from_string && account_name) {
548 gchar *name = account_name;
549 ModestPair *pair = modest_pair_new ((gpointer) name,
550 (gpointer) from_string , TRUE);
551 transports = g_slist_prepend (transports, pair);
556 cursor = cursor->next;
558 g_slist_free (accounts); /* only free the accounts, not the elements,
559 * because they are used in the pairlist */
563 static void window_focus (GtkWindow *window,
567 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
571 scroll_drag_timeout (gpointer userdata)
573 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
574 ModestMsgEditWindowPrivate *priv;
576 /* It could happen that the window was already closed */
577 if (!GTK_WIDGET_VISIBLE (win))
580 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
582 correct_scroll_without_drag_check (win, TRUE);
584 priv->scroll_drag_timeout_id = 0;
590 correct_scroll_without_drag_check_idle (gpointer userdata)
592 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
593 ModestMsgEditWindowPrivate *priv;
595 GdkRectangle rectangle;
596 gint offset_min, offset_max;
600 /* It could happen that the window was already closed */
601 if (!GTK_WIDGET_VISIBLE (w))
604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
606 insert = gtk_text_buffer_get_insert (priv->text_buffer);
607 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
609 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
610 offset_min = priv->msg_body->allocation.y + rectangle.y;
611 offset_max = offset_min + rectangle.height;
613 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
614 offset_min = MAX (offset_min - 48, 0);
615 offset_max = MIN (offset_max + 48, vadj->upper);
617 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
619 priv->correct_scroll_idle = 0;
624 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
626 ModestMsgEditWindowPrivate *priv;
628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
630 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
633 if (priv->correct_scroll_idle > 0) {
637 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
638 (GSourceFunc) correct_scroll_without_drag_check_idle,
644 correct_scroll (ModestMsgEditWindow *w)
646 ModestMsgEditWindowPrivate *priv;
648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
649 if (gtk_grab_get_current () == priv->msg_body) {
650 if (priv->scroll_drag_timeout_id == 0) {
651 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
653 (GSourceFunc) scroll_drag_timeout,
660 correct_scroll_without_drag_check (w, TRUE);
664 text_buffer_end_user_action (GtkTextBuffer *buffer,
665 ModestMsgEditWindow *userdata)
668 correct_scroll (userdata);
672 text_buffer_mark_set (GtkTextBuffer *buffer,
675 ModestMsgEditWindow *userdata)
677 gtk_text_buffer_begin_user_action (buffer);
678 gtk_text_buffer_end_user_action (buffer);
682 cut_clipboard_check (GtkTextView *text_view,
685 GtkTextBuffer *buffer;
687 buffer = gtk_text_view_get_buffer (text_view);
688 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
689 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
694 copy_clipboard_check (GtkTextView *text_view,
697 GtkTextBuffer *buffer;
699 buffer = gtk_text_view_get_buffer (text_view);
700 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
701 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
706 attachment_deleted (ModestAttachmentsView *attachments_view,
709 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
714 connect_signals (ModestMsgEditWindow *obj)
716 ModestMsgEditWindowPrivate *priv;
718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
720 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
721 G_CALLBACK (text_buffer_refresh_attributes), obj);
722 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
723 G_CALLBACK (text_buffer_can_undo), obj);
724 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
725 G_CALLBACK (text_buffer_can_redo), obj);
726 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
727 G_CALLBACK (body_changed), obj);
728 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
729 G_CALLBACK (body_insert_text), obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
731 G_CALLBACK (body_changed), obj);
732 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
733 G_CALLBACK (text_buffer_end_user_action), obj);
734 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
735 G_CALLBACK (text_buffer_mark_set), obj);
736 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
737 G_CALLBACK (text_buffer_apply_tag), obj);
738 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
739 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
740 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
741 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
742 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
743 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
745 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
746 G_CALLBACK (modest_ui_actions_on_send), obj);
748 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
749 G_CALLBACK (from_field_changed), obj);
751 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
752 G_CALLBACK (msg_body_focus), obj);
753 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
754 G_CALLBACK (msg_body_focus), obj);
755 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
756 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
757 "changed", G_CALLBACK (recpt_field_changed), obj);
758 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
759 "changed", G_CALLBACK (recpt_field_changed), obj);
760 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
761 "changed", G_CALLBACK (recpt_field_changed), obj);
762 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
763 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
764 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
766 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
767 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
769 priv->clipboard_change_handler_id =
770 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
771 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
772 priv->default_clipboard_change_handler_id =
773 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
774 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
776 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
777 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
778 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
782 init_wp_text_view_style ()
784 static gboolean initialized = FALSE;
787 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
793 init_window (ModestMsgEditWindow *obj)
795 GtkWidget *to_caption, *subject_caption;
796 GtkWidget *main_vbox;
797 ModestMsgEditWindowPrivate *priv;
798 GtkActionGroup *action_group;
799 ModestWindowPrivate *parent_priv;
800 GdkPixbuf *window_icon = NULL;
801 GError *error = NULL;
803 GtkSizeGroup *title_size_group;
804 GtkSizeGroup *value_size_group;
805 GtkWidget *window_box;
806 GtkWidget *window_align;
807 #if (GTK_MINOR_VERSION >= 10)
808 GdkAtom deserialize_type;
810 GtkWidget *from_send_hbox;
811 GtkWidget *send_icon;
812 GtkWidget *attachments_label;
814 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
815 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
817 parent_priv->ui_manager = gtk_ui_manager_new();
818 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
819 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
821 /* Add common actions */
822 gtk_action_group_add_actions (action_group,
823 modest_msg_edit_action_entries,
824 G_N_ELEMENTS (modest_msg_edit_action_entries),
826 gtk_action_group_add_actions (action_group,
827 hildon2_msg_edit_action_entries,
828 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
830 gtk_action_group_add_toggle_actions (action_group,
831 modest_msg_edit_toggle_action_entries,
832 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
834 gtk_action_group_add_radio_actions (action_group,
835 modest_msg_edit_alignment_radio_action_entries,
836 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
838 G_CALLBACK (modest_ui_actions_on_change_justify),
840 gtk_action_group_add_radio_actions (action_group,
841 modest_msg_edit_priority_action_entries,
842 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
844 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
846 gtk_action_group_add_radio_actions (action_group,
847 modest_msg_edit_file_format_action_entries,
848 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
849 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
850 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
852 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
853 g_object_unref (action_group);
855 /* Load the UI definition */
856 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
859 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
860 g_clear_error (&error);
863 /* Add accelerators */
864 gtk_window_add_accel_group (GTK_WINDOW (obj),
865 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
867 parent_priv->menubar = NULL;
869 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
870 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
872 /* Note: This ModestPairList* must exist for as long as the picker
873 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
874 * so it can't know how to manage its memory. */
875 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
876 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
878 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
879 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
880 _("mail_va_from"), priv->from_field);
881 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
882 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
883 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
885 priv->to_field = modest_recpt_editor_new ();
886 priv->cc_field = modest_recpt_editor_new ();
887 priv->bcc_field = modest_recpt_editor_new ();
888 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
889 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
890 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
891 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
892 priv->priority_icon = gtk_image_new ();
893 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
894 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
895 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
896 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
897 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
898 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
899 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
900 priv->attachments_view = modest_attachments_view_new (NULL);
901 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
902 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
904 priv->header_box = gtk_vbox_new (FALSE, 0);
906 to_caption = _create_addressbook_box
907 (title_size_group, value_size_group,
908 _("mail_va_to"), priv->to_field);
909 priv->cc_caption = _create_addressbook_box
910 (title_size_group, value_size_group,
911 _("mail_va_cc"), priv->cc_field);
912 priv->bcc_caption = _create_addressbook_box
913 (title_size_group, value_size_group,
914 _("mail_va_hotfix1"), priv->bcc_field);
915 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
916 _("mail_va_subject"), FALSE, priv->subject_box);
917 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
918 _("mail_va_attachment"),
920 priv->attachments_view,
921 HILDON_SIZE_AUTO_WIDTH |
922 HILDON_SIZE_AUTO_HEIGHT);
923 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
924 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
927 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
928 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
929 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
930 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
932 g_object_unref (title_size_group);
933 g_object_unref (value_size_group);
935 from_send_hbox = gtk_hbox_new (FALSE, 0);
936 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
937 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
939 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
940 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
941 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
942 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
943 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
944 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
945 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
947 init_wp_text_view_style ();
949 priv->msg_body = modest_wp_text_view_new ();
952 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
953 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
954 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
955 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
956 #if (GTK_MINOR_VERSION >= 10)
957 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
958 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
960 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
961 deserialize_type, TRUE);
963 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
965 priv->find_toolbar = hildon_find_toolbar_new (NULL);
966 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
968 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
970 priv->pannable = hildon_pannable_area_new ();
972 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
974 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
975 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
976 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
978 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
979 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
980 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
982 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
983 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
985 window_box = gtk_vbox_new (FALSE, 0);
986 gtk_container_add (GTK_CONTAINER(obj), window_box);
988 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
990 /* Set window icon */
991 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
993 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
994 g_object_unref (window_icon);
999 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1001 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1003 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1004 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1005 priv->clipboard_change_handler_id))
1006 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1007 priv->clipboard_change_handler_id);
1008 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1009 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1010 priv->default_clipboard_change_handler_id))
1011 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1012 priv->default_clipboard_change_handler_id);
1014 if (priv->account_removed_handler_id &&
1015 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1016 priv->account_removed_handler_id))
1017 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1018 priv->account_removed_handler_id);
1022 modest_msg_edit_window_finalize (GObject *obj)
1024 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1026 if (priv->max_chars_banner) {
1027 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1028 priv->max_chars_banner = FALSE;
1031 /* Sanity check: shouldn't be needed, the window mgr should
1032 call this function before */
1033 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1035 if (priv->font_dialog != NULL) {
1036 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1039 if (priv->clipboard_text != NULL) {
1040 g_free (priv->clipboard_text);
1041 priv->clipboard_text = NULL;
1044 if (priv->draft_msg != NULL) {
1045 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1046 if (TNY_IS_HEADER (header)) {
1047 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1048 modest_window_mgr_unregister_header (mgr, header);
1050 g_object_unref (priv->draft_msg);
1051 priv->draft_msg = NULL;
1053 if (priv->outbox_msg != NULL) {
1054 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1055 if (TNY_IS_HEADER (header)) {
1056 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1057 modest_window_mgr_unregister_header (mgr, header);
1059 g_object_unref (priv->outbox_msg);
1060 priv->outbox_msg = NULL;
1062 if (priv->correct_scroll_idle > 0) {
1063 g_source_remove (priv->correct_scroll_idle);
1064 priv->correct_scroll_idle = 0;
1066 if (priv->scroll_drag_timeout_id > 0) {
1067 g_source_remove (priv->scroll_drag_timeout_id);
1068 priv->scroll_drag_timeout_id = 0;
1070 if (priv->clipboard_owner_idle > 0) {
1071 g_source_remove (priv->clipboard_owner_idle);
1072 priv->clipboard_owner_idle = 0;
1074 if (priv->original_account_name)
1075 g_free (priv->original_account_name);
1076 if (priv->original_mailbox)
1077 g_free (priv->original_mailbox);
1078 g_free (priv->msg_uid);
1079 g_free (priv->last_search);
1080 g_free (priv->references);
1081 g_free (priv->in_reply_to);
1082 g_object_unref (priv->faces_model);
1083 g_object_unref (priv->sizes_model);
1084 g_object_unref (priv->attachments);
1085 g_object_unref (priv->images);
1087 /* This had to stay alive for as long as the picker that used it: */
1088 modest_pair_list_free (priv->from_field_protos);
1090 G_OBJECT_CLASS(parent_class)->finalize (obj);
1094 pixbuf_size_prepared (GdkPixbufLoader *loader,
1097 ModestMsgEditWindow *self)
1099 gint new_height, new_width;
1102 new_height = height;
1106 if (width > IMAGE_MAX_WIDTH) {
1107 new_height = height * IMAGE_MAX_WIDTH / width;
1108 new_width = IMAGE_MAX_WIDTH;
1111 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1115 pixbuf_from_stream (TnyStream *stream,
1116 const gchar *mime_type,
1117 guint64 *stream_size,
1118 ModestMsgEditWindow *self)
1120 GdkPixbufLoader *loader;
1123 GError *error = NULL;
1127 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1129 if (loader == NULL) {
1134 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1136 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1138 tny_stream_reset (TNY_STREAM (stream));
1139 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1140 unsigned char read_buffer[128];
1142 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1144 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1147 /* Allow some UI responsiveness */
1148 while (gtk_events_pending ())
1149 gtk_main_iteration ();
1151 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1153 gdk_pixbuf_loader_close (loader, &error);
1156 g_error_free (error);
1157 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1159 g_object_ref (pixbuf);
1160 g_object_unref (loader);
1165 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1166 GdkPixbuf *new_pixbuf;
1168 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1169 gdk_pixbuf_get_width (pixbuf);
1170 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1171 g_object_unref (pixbuf);
1172 pixbuf = new_pixbuf;
1176 *stream_size = size;
1182 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1184 ModestMsgEditWindowPrivate *priv;
1187 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1189 g_object_ref (self);
1190 for (iter = tny_list_create_iterator (attachments);
1191 !tny_iterator_is_done (iter);
1192 tny_iterator_next (iter)) {
1193 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1194 const gchar *cid = tny_mime_part_get_content_id (part);
1195 const gchar *mime_type = tny_mime_part_get_content_type (part);
1196 if ((cid != NULL)&&(mime_type != NULL)) {
1197 guint64 stream_size;
1198 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1199 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1202 g_object_unref (stream);
1204 if (pixbuf != NULL) {
1205 priv->images_count ++;
1206 priv->images_size += stream_size;
1207 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1208 g_object_unref (pixbuf);
1211 g_object_unref (part);
1213 g_object_unref (iter);
1214 g_object_unref (self);
1218 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1220 TnyMimePart *parent = NULL;
1221 const gchar *content_type = NULL;
1222 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1224 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1226 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1227 parent = g_object_ref (msg);
1228 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1229 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1232 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1233 iter = tny_list_create_iterator (parts);
1234 while (!tny_iterator_is_done (iter)) {
1236 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1237 content_type = tny_mime_part_get_content_type (part);
1238 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1242 g_object_unref (part);
1244 tny_iterator_next (iter);
1246 g_object_unref (iter);
1247 g_object_unref (parts);
1250 if (parent != NULL) {
1251 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1254 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1255 iter = tny_list_create_iterator (parts);
1256 while (!tny_iterator_is_done (iter)) {
1258 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1259 content_type = tny_mime_part_get_content_type (part);
1260 if (content_type && g_str_has_prefix (content_type, "image/")) {
1261 tny_list_prepend (priv->images, (GObject *) part);
1263 g_object_unref (part);
1264 tny_iterator_next (iter);
1266 g_object_unref (iter);
1267 g_object_unref (parts);
1268 g_object_unref (parent);
1273 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1276 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1278 for (iter = tny_list_create_iterator (attachments) ;
1279 !tny_iterator_is_done (iter);
1280 tny_iterator_next (iter)) {
1281 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1282 const gchar *cid = tny_mime_part_get_content_id (part);
1284 char *invalid = NULL;
1285 gint int_cid = strtol (cid, &invalid, 10);
1286 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1287 priv->next_cid = int_cid + 1;
1290 g_object_unref (part);
1292 g_object_unref (iter);
1296 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1299 gchar *to, *cc, *bcc, *subject;
1301 ModestMsgEditWindowPrivate *priv;
1302 ModestWindowPrivate *parent_priv;
1304 TnyHeaderFlags priority_flags;
1305 TnyFolder *msg_folder;
1306 gboolean is_html = FALSE;
1307 gboolean field_view_set;
1309 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1310 g_return_if_fail (TNY_IS_MSG (msg));
1312 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1313 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1315 header = tny_msg_get_header (msg);
1316 to = tny_header_dup_to (header);
1317 cc = tny_header_dup_cc (header);
1318 bcc = tny_header_dup_bcc (header);
1319 subject = tny_header_dup_subject (header);
1321 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1322 priority_flags = tny_header_get_priority (header);
1325 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1327 field_view_set = TRUE;
1329 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1330 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1331 gtk_widget_show (priv->cc_caption);
1332 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1333 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1334 gtk_widget_hide (priv->cc_caption);
1335 field_view_set = FALSE;
1337 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1339 field_view_set = TRUE;
1341 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1342 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1343 gtk_widget_show (priv->bcc_caption);
1344 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1345 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1346 gtk_widget_hide (priv->bcc_caption);
1347 field_view_set = FALSE;
1349 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1353 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1354 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1357 update_window_title (self);
1359 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1360 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1362 if ((body == NULL)||(body[0] == '\0')) {
1364 body = modest_text_utils_convert_to_html ("");
1367 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1368 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1371 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1374 /* Add attachments to the view */
1375 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1376 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1377 if (tny_list_get_length (priv->attachments) == 0) {
1378 gtk_widget_hide (priv->attachments_caption);
1380 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1381 gtk_widget_show_all (priv->attachments_caption);
1383 get_related_images (self, msg);
1384 update_next_cid (self, priv->attachments);
1385 update_next_cid (self, priv->images);
1386 replace_with_images (self, priv->images);
1388 if (preserve_is_rich && !is_html) {
1389 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1390 /* Get the default format required from configuration */
1391 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1392 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1395 /* Set the default focus depending on having already a To: field or not */
1396 if ((!to)||(*to == '\0')) {
1397 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1399 gtk_widget_grab_focus (priv->msg_body);
1402 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1404 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1405 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1407 modest_msg_edit_window_set_modified (self, FALSE);
1409 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1410 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1411 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1412 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1414 if (priv->msg_uid) {
1415 g_free (priv->msg_uid);
1416 priv->msg_uid = NULL;
1419 /* we should set a reference to the incoming message if it is a draft */
1420 msg_folder = tny_msg_get_folder (msg);
1422 if (modest_tny_folder_is_local_folder (msg_folder)) {
1423 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1424 if (type == TNY_FOLDER_TYPE_INVALID)
1425 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1427 if (type == TNY_FOLDER_TYPE_DRAFTS)
1428 priv->draft_msg = g_object_ref(msg);
1429 if (type == TNY_FOLDER_TYPE_OUTBOX)
1430 priv->outbox_msg = g_object_ref(msg);
1431 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1433 g_object_unref (msg_folder);
1444 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1446 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1447 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1448 GtkWidget *placeholder;
1449 GtkWidget *tool_item;
1454 GtkWidget *sizes_menu;
1455 GtkWidget *fonts_menu;
1461 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1462 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1463 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1464 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1466 /* Font color placeholder */
1467 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1468 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1471 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1472 priv->font_color_button = hildon_color_button_new ();
1473 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1474 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1475 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1476 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1477 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1478 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1479 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1480 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1482 G_CALLBACK (modest_msg_edit_window_color_button_change),
1485 /* Font size and face placeholder */
1486 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1487 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1489 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1490 priv->size_tool_button_label = gtk_label_new (NULL);
1491 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1492 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1493 size_text, "</span>", NULL);
1494 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1495 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1497 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1498 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1499 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1500 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1501 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1502 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1503 gtk_widget_set_sensitive (arrow, FALSE);
1504 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1505 sizes_menu = gtk_menu_new ();
1506 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1507 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1510 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1511 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1513 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1517 if (wp_font_size[size_index] == 12)
1518 priv->current_size_index = size_index;
1522 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1523 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1524 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1525 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1526 priv->font_size_toolitem = tool_item;
1529 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1530 priv->font_tool_button_label = gtk_label_new (NULL);
1531 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1532 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1533 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1535 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1536 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1537 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1538 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1539 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1540 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1541 gtk_widget_set_sensitive (arrow, FALSE);
1542 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1543 fonts_menu = gtk_menu_new ();
1544 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1545 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1548 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1550 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1551 0, wp_get_font_name (font_index),
1554 if (font_index == DEFAULT_FONT)
1555 priv->current_face_index = font_index;
1557 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1558 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1559 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1560 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1561 priv->font_face_toolitem = tool_item;
1563 /* Set expand and homogeneous for remaining items */
1564 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1565 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1566 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1567 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1568 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1569 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1571 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1572 will not show the tool items added to the placeholders) */
1573 gtk_widget_show_all (parent_priv->toolbar);
1575 /* Set the no show all *after* showing all items. We do not
1576 want the toolbar to be shown with a show all because it
1577 could go agains the gconf setting regarding showing or not
1578 the toolbar of the editor window */
1579 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1585 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1588 ModestWindowPrivate *parent_priv;
1589 ModestMsgEditWindowPrivate *priv;
1590 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1591 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1592 ModestWindowMgr *mgr = NULL;
1594 g_return_val_if_fail (msg, NULL);
1595 g_return_val_if_fail (account_name, NULL);
1597 mgr = modest_runtime_get_window_mgr ();
1599 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1602 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1604 /* Menubar. Update the state of some toggles */
1605 priv->from_field_protos = get_transports ();
1606 priv->original_mailbox = NULL;
1607 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1608 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1609 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1610 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1611 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1612 priv->original_mailbox = g_strdup (mailbox);
1613 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1614 /* We set the first mailbox as the active mailbox */
1615 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1616 if (priv->original_mailbox != NULL)
1617 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1618 (gpointer) priv->original_mailbox);
1620 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1621 (gpointer) account_name);
1623 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1625 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1626 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1628 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1629 hildon_touch_selector_get_current_text
1630 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1631 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1632 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1635 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1637 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1639 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1640 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1642 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1644 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1645 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1646 /* Add common dimming rules */
1647 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1648 modest_msg_edit_window_toolbar_dimming_entries,
1649 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1650 MODEST_WINDOW (obj));
1651 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1652 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1653 MODEST_WINDOW (obj));
1654 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1655 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1656 MODEST_WINDOW (obj));
1657 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1658 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1659 MODEST_WINDOW (obj));
1660 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1661 G_CALLBACK (modest_ui_dimming_rules_on_send),
1662 MODEST_WINDOW (obj));
1663 /* Insert dimming rules group for this window */
1664 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1665 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1667 /* Setup app menu */
1668 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1670 /* Checks the dimming rules */
1671 g_object_unref (toolbar_rules_group);
1672 g_object_unref (clipboard_rules_group);
1673 gtk_widget_hide (priv->priority_icon);
1674 gtk_widget_queue_resize (priv->subject_box);
1675 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1677 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1679 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1680 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1681 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1682 priv->update_caption_visibility = TRUE;
1684 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1686 /* Track account-removed signal, this window should be closed
1687 in the case we're creating a mail associated to the account
1689 priv->account_removed_handler_id =
1690 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1692 G_CALLBACK(on_account_removed),
1695 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1697 return (ModestWindow*) obj;
1701 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1703 GString **string_buffer = (GString **) user_data;
1705 *string_buffer = g_string_append (*string_buffer, buffer);
1711 * @result: A new string which should be freed with g_free().
1714 get_formatted_data (ModestMsgEditWindow *edit_window)
1716 ModestMsgEditWindowPrivate *priv;
1717 GString *string_buffer = g_string_new ("");
1719 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1721 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1723 modest_text_utils_hyperlinkify (string_buffer);
1725 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1727 return g_string_free (string_buffer, FALSE);
1732 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1735 const gchar *account_name;
1736 ModestMsgEditWindowPrivate *priv;
1737 TnyIterator *att_iter;
1738 const gchar *picker_active_id;
1740 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1744 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1745 g_return_val_if_fail (picker_active_id, NULL);
1746 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1748 /* don't free these (except from) */
1749 data = g_slice_new0 (MsgData);
1750 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1751 data->account_name = g_strdup (account_name);
1752 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1753 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1754 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1755 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1756 data->references = g_strdup (priv->references);
1757 data->in_reply_to = g_strdup (priv->in_reply_to);
1758 if (priv->draft_msg) {
1759 data->draft_msg = g_object_ref (priv->draft_msg);
1760 } else if (priv->outbox_msg) {
1761 data->draft_msg = g_object_ref (priv->outbox_msg);
1763 data->draft_msg = NULL;
1766 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1768 gtk_text_buffer_get_bounds (buf, &b, &e);
1769 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1771 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1772 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1774 data->html_body = NULL;
1776 /* deep-copy the data */
1777 att_iter = tny_list_create_iterator (priv->attachments);
1778 data->attachments = NULL;
1779 while (!tny_iterator_is_done (att_iter)) {
1780 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1781 if (!(TNY_IS_MIME_PART(part))) {
1782 g_warning ("strange data in attachment list");
1783 g_object_unref (part);
1784 tny_iterator_next (att_iter);
1787 data->attachments = g_list_append (data->attachments,
1789 tny_iterator_next (att_iter);
1791 g_object_unref (att_iter);
1793 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1794 att_iter = tny_list_create_iterator (priv->images);
1795 data->images = NULL;
1796 while (!tny_iterator_is_done (att_iter)) {
1797 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1799 if (!(TNY_IS_MIME_PART(part))) {
1800 g_warning ("strange data in attachment list");
1801 g_object_unref (part);
1802 tny_iterator_next (att_iter);
1805 cid = tny_mime_part_get_content_id (part);
1807 gchar *image_tag_id;
1808 GtkTextTag *image_tag;
1810 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1811 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1812 g_free (image_tag_id);
1814 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1816 ((gtk_text_iter_has_tag (&iter, image_tag))||
1817 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1818 data->images = g_list_append (data->images,
1819 g_object_ref (part));
1821 g_object_unref (part);
1822 tny_iterator_next (att_iter);
1824 g_object_unref (att_iter);
1826 data->priority_flags = priv->priority_flags;
1833 unref_gobject (GObject *obj, gpointer data)
1835 if (!G_IS_OBJECT(obj))
1837 g_object_unref (obj);
1841 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1844 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1852 g_free (data->from);
1853 g_free (data->subject);
1854 g_free (data->plain_body);
1855 g_free (data->html_body);
1856 g_free (data->account_name);
1857 g_free (data->references);
1858 g_free (data->in_reply_to);
1860 if (data->draft_msg != NULL) {
1861 g_object_unref (data->draft_msg);
1862 data->draft_msg = NULL;
1865 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1866 g_list_free (data->attachments);
1867 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1868 g_list_free (data->images);
1870 g_slice_free (MsgData, data);
1874 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1876 guint64 *parts_size)
1878 ModestMsgEditWindowPrivate *priv;
1880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1882 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1884 /* TODO: add images */
1885 *parts_size += priv->images_size;
1886 *parts_count += priv->images_count;
1891 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1894 ModestMsgEditWindowPrivate *priv = NULL;
1895 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1897 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1899 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1901 return MODEST_MSG_EDIT_FORMAT_HTML;
1903 return MODEST_MSG_EDIT_FORMAT_TEXT;
1907 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1908 ModestMsgEditFormat format)
1910 ModestMsgEditWindowPrivate *priv;
1911 ModestWindowPrivate *parent_priv;
1913 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1914 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1915 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1918 case MODEST_MSG_EDIT_FORMAT_HTML:
1919 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1920 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1922 case MODEST_MSG_EDIT_FORMAT_TEXT:
1923 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1924 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1927 g_return_if_reached ();
1931 ModestMsgEditFormatState *
1932 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1934 ModestMsgEditFormatState *format_state = NULL;
1935 ModestMsgEditWindowPrivate *priv;
1936 WPTextBufferFormat *buffer_format;
1938 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1940 buffer_format = g_new0 (WPTextBufferFormat, 1);
1941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1943 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1945 format_state = g_new0 (ModestMsgEditFormatState, 1);
1946 format_state->bold = buffer_format->bold&0x1;
1947 format_state->italics = buffer_format->italic&0x1;
1948 format_state->bullet = buffer_format->bullet&0x1;
1949 format_state->color = buffer_format->color;
1950 format_state->font_size = buffer_format->font_size;
1951 format_state->font_family = wp_get_font_name (buffer_format->font);
1952 format_state->justification = buffer_format->justification;
1953 g_free (buffer_format);
1955 return format_state;
1960 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1961 const ModestMsgEditFormatState *format_state)
1963 ModestMsgEditWindowPrivate *priv;
1964 WPTextBufferFormat *buffer_format;
1965 WPTextBufferFormat *current_format;
1967 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1968 g_return_if_fail (format_state != NULL);
1970 buffer_format = g_new0 (WPTextBufferFormat, 1);
1971 current_format = g_new0 (WPTextBufferFormat, 1);
1973 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1974 gtk_widget_grab_focus (priv->msg_body);
1975 buffer_format->bold = (format_state->bold != FALSE);
1976 buffer_format->italic = (format_state->italics != FALSE);
1977 buffer_format->color = format_state->color;
1978 buffer_format->font_size = format_state->font_size;
1979 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1980 buffer_format->justification = format_state->justification;
1981 buffer_format->bullet = format_state->bullet;
1983 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1985 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1986 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1987 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1988 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1989 buffer_format->cs.font = (buffer_format->font != current_format->font);
1990 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1991 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1993 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1994 if (buffer_format->cs.bold) {
1995 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1996 GINT_TO_POINTER (buffer_format->bold&0x1));
1998 if (buffer_format->cs.italic) {
1999 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2000 GINT_TO_POINTER (buffer_format->italic&0x1));
2002 if (buffer_format->cs.color) {
2003 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2004 GINT_TO_POINTER (&(buffer_format->color)));
2006 if (buffer_format->cs.font_size) {
2007 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2008 GINT_TO_POINTER (buffer_format->font_size));
2010 if (buffer_format->cs.justification) {
2011 switch (buffer_format->justification) {
2012 case GTK_JUSTIFY_LEFT:
2013 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2014 GINT_TO_POINTER(TRUE));
2016 case GTK_JUSTIFY_CENTER:
2017 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2018 GINT_TO_POINTER(TRUE));
2020 case GTK_JUSTIFY_RIGHT:
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2022 GINT_TO_POINTER(TRUE));
2029 if (buffer_format->cs.font) {
2030 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2031 GINT_TO_POINTER (buffer_format->font));
2033 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2034 if (buffer_format->cs.bullet) {
2035 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2036 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2038 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2040 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2042 g_free (buffer_format);
2043 g_free (current_format);
2045 /* Check dimming rules */
2046 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2047 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2051 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2053 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2055 ModestWindowPrivate *parent_priv;
2056 ModestMsgEditWindowPrivate *priv;
2058 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2059 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2061 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2062 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2063 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2064 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2066 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2067 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2068 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2071 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2073 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2074 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2076 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2077 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2079 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2080 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2083 switch (buffer_format->justification)
2085 case GTK_JUSTIFY_LEFT:
2086 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2088 case GTK_JUSTIFY_CENTER:
2089 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2091 case GTK_JUSTIFY_RIGHT:
2092 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2099 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2101 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2102 G_CALLBACK (modest_msg_edit_window_color_button_change),
2104 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2105 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2106 G_CALLBACK (modest_msg_edit_window_color_button_change),
2109 if (priv->current_size_index != buffer_format->font_size) {
2113 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2114 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2118 priv->current_size_index = buffer_format->font_size;
2120 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2121 markup = g_strconcat ("<span font_family='Sans'>",
2122 size_text, "</span>", NULL);
2124 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2128 gtk_tree_path_free (path);
2131 if (priv->current_face_index != buffer_format->font) {
2135 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2136 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2140 priv->current_face_index = buffer_format->font;
2141 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2142 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2143 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2150 g_free (buffer_format);
2154 #ifdef MODEST_HILDON_VERSION_0
2156 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2159 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2160 ModestMsgEditWindowPrivate *priv;
2161 GtkWidget *dialog = NULL;
2163 GdkColor *new_color = NULL;
2165 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2166 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2168 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2169 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2170 g_free (buffer_format);
2172 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2173 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2174 if (new_color != NULL) {
2175 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2176 (gpointer) new_color);
2179 gtk_widget_destroy (dialog);
2184 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2187 ModestMsgEditWindowPrivate *priv;
2188 GtkWidget *dialog = NULL;
2190 GdkColor *old_color = NULL;
2191 const GdkColor *new_color = NULL;
2193 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2194 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2196 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2197 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2199 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2200 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2201 if (new_color != NULL)
2202 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2204 gtk_widget_destroy (dialog);
2210 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2213 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2214 ModestMsgEditWindowPrivate *priv;
2215 GtkWidget *dialog = NULL;
2217 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2218 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2220 dialog = hildon_color_chooser_new ();
2221 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2222 g_free (buffer_format);
2224 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2226 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2227 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2230 gtk_widget_destroy (dialog);
2235 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2238 ModestMsgEditWindowPrivate *priv;
2239 GtkWidget *dialog = NULL;
2240 GdkColor *old_color = NULL;
2242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2243 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2245 dialog = hildon_color_chooser_new ();
2246 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2248 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2250 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2251 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2253 gtk_widget_destroy (dialog);
2256 #endif /*!MODEST_HILDON_VERSION_0*/
2261 create_stream_for_uri (const gchar* uri)
2266 TnyStream *result = NULL;
2268 GnomeVFSHandle *handle = NULL;
2269 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2270 if (test == GNOME_VFS_OK) {
2271 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2272 /* Streams over OBEX (Bluetooth) are not seekable but
2273 * we expect them to be (we might need to read them
2274 * several times). So if this is a Bluetooth URI just
2275 * read the whole file into memory (this is not a fast
2276 * protocol so we can assume that these files are not
2277 * going to be very big) */
2278 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2279 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2280 TnyStream *memstream = tny_camel_mem_stream_new ();
2281 tny_stream_write_to_stream (vfssstream, memstream);
2282 g_object_unref (vfssstream);
2285 result = vfssstream;
2293 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2296 ModestMsgEditWindowPrivate *priv;
2297 GtkWidget *dialog = NULL;
2299 GSList *uris = NULL;
2300 GSList *uri_node = NULL;
2302 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2304 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2305 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2306 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2308 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2310 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2311 GTK_WINDOW (dialog), GTK_WINDOW (window));
2313 response = gtk_dialog_run (GTK_DIALOG (dialog));
2315 case GTK_RESPONSE_OK:
2317 gchar *current_folder;
2318 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2319 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2320 if (current_folder && current_folder != '\0') {
2322 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2323 current_folder, &err);
2325 g_debug ("Error storing latest used folder: %s", err->message);
2329 g_free (current_folder);
2335 gtk_widget_destroy (dialog);
2337 g_object_ref (window);
2338 /* The operation could take some time so allow the dialog to be closed */
2339 while (gtk_events_pending ())
2340 gtk_main_iteration ();
2342 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2344 GnomeVFSHandle *handle = NULL;
2345 GnomeVFSResult result;
2346 GtkTextIter position;
2347 GtkTextMark *insert_mark;
2349 uri = (const gchar *) uri_node->data;
2350 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2351 if (result == GNOME_VFS_OK) {
2353 GnomeVFSFileInfo *info;
2354 gchar *filename, *basename, *escaped_filename;
2355 TnyMimePart *mime_part;
2357 const gchar *mime_type = NULL;
2358 GnomeVFSURI *vfs_uri;
2359 guint64 stream_size;
2361 gnome_vfs_close (handle);
2362 vfs_uri = gnome_vfs_uri_new (uri);
2364 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2365 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2366 g_free (escaped_filename);
2367 gnome_vfs_uri_unref (vfs_uri);
2368 info = gnome_vfs_file_info_new ();
2370 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2371 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2373 mime_type = gnome_vfs_file_info_get_mime_type (info);
2375 mime_part = tny_platform_factory_new_mime_part
2376 (modest_runtime_get_platform_factory ());
2378 TnyStream *stream = create_stream_for_uri (uri);
2380 if (stream == NULL) {
2382 modest_platform_information_banner (NULL, NULL,
2383 _FM("sfil_ib_opening_not_allowed"));
2385 g_object_unref (mime_part);
2386 gnome_vfs_file_info_unref (info);
2390 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2392 content_id = g_strdup_printf ("%d", priv->next_cid);
2393 tny_mime_part_set_content_id (mime_part, content_id);
2394 g_free (content_id);
2397 basename = g_path_get_basename (filename);
2398 tny_mime_part_set_filename (mime_part, basename);
2401 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2403 if (pixbuf != NULL) {
2404 priv->images_size += stream_size;
2405 priv->images_count ++;
2406 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2407 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2408 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2409 tny_mime_part_get_content_id (mime_part), pixbuf);
2410 g_object_unref (pixbuf);
2412 tny_list_prepend (priv->images, (GObject *) mime_part);
2413 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2415 modest_platform_information_banner (NULL, NULL,
2416 _("mail_ib_file_operation_failed"));
2420 g_object_unref (mime_part);
2421 gnome_vfs_file_info_unref (info);
2425 g_object_unref (window);
2429 on_attach_file_response (GtkDialog *dialog,
2433 GSList *uris = NULL;
2435 GnomeVFSFileSize total_size, allowed_size;
2436 ModestMsgEditWindow *window;
2437 ModestMsgEditWindowPrivate *priv;
2442 case GTK_RESPONSE_OK:
2444 gchar *current_folder;
2446 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2447 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2448 if (current_folder && current_folder != '\0') {
2450 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2451 current_folder, &err);
2453 g_debug ("Error storing latest used folder: %s", err->message);
2457 g_free (current_folder);
2464 window = MODEST_MSG_EDIT_WINDOW (user_data);
2465 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2467 /* allowed size is the maximum size - what's already there */
2468 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2469 &att_num, &att_size);
2470 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2473 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2475 const gchar *uri = (const gchar *) uri_node->data;
2478 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2480 if (total_size > allowed_size) {
2481 g_warning ("%s: total size: %u",
2482 __FUNCTION__, (unsigned int)total_size);
2485 allowed_size -= total_size;
2487 g_slist_foreach (uris, (GFunc) g_free, NULL);
2488 g_slist_free (uris);
2490 gtk_widget_destroy (GTK_WIDGET (dialog));
2494 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2496 GtkWidget *dialog = NULL;
2497 ModestMsgEditWindowPrivate *priv;
2500 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2502 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2504 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2507 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2508 GTK_FILE_CHOOSER_ACTION_OPEN);
2509 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2510 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2511 if (conf_folder && conf_folder[0] != '\0') {
2512 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2515 /* Set the default folder to images folder */
2516 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2517 ".documents", NULL);
2518 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2519 g_free (docs_folder);
2521 g_free (conf_folder);
2522 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2523 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2524 GTK_WINDOW (dialog), GTK_WINDOW (window));
2526 /* Connect to response & show */
2527 g_signal_connect (dialog, "response",
2528 G_CALLBACK (on_attach_file_response), window);
2529 gtk_widget_show (dialog);
2534 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2536 GnomeVFSFileSize allowed_size)
2539 GnomeVFSHandle *handle = NULL;
2540 ModestMsgEditWindowPrivate *priv;
2541 GnomeVFSResult result;
2542 GnomeVFSFileSize size = 0;
2543 g_return_val_if_fail (window, 0);
2544 g_return_val_if_fail (uri, 0);
2546 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2548 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2549 if (result == GNOME_VFS_OK) {
2550 TnyMimePart *mime_part;
2552 const gchar *mime_type = NULL;
2554 gchar *escaped_filename;
2557 GnomeVFSFileInfo *info;
2558 GnomeVFSURI *vfs_uri;
2560 gnome_vfs_close (handle);
2561 vfs_uri = gnome_vfs_uri_new (uri);
2564 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2565 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2566 g_free (escaped_filename);
2567 gnome_vfs_uri_unref (vfs_uri);
2569 info = gnome_vfs_file_info_new ();
2571 if (gnome_vfs_get_file_info (uri,
2573 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2575 mime_type = gnome_vfs_file_info_get_mime_type (info);
2576 mime_part = tny_platform_factory_new_mime_part
2577 (modest_runtime_get_platform_factory ());
2579 /* try to get the attachment's size; this may fail for weird
2580 * file systems, like obex, upnp... */
2581 if (allowed_size != 0 &&
2582 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2584 if (size > allowed_size) {
2585 modest_platform_information_banner (NULL, NULL,
2586 _FM("sfil_ib_opening_not_allowed"));
2591 g_warning ("%s: could not get attachment size", __FUNCTION__);
2593 stream = create_stream_for_uri (uri);
2595 if (stream == NULL) {
2597 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2599 g_object_unref (mime_part);
2601 gnome_vfs_file_info_unref (info);
2605 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2606 g_object_unref (stream);
2608 content_id = g_strdup_printf ("%d", priv->next_cid);
2609 tny_mime_part_set_content_id (mime_part, content_id);
2610 g_free (content_id);
2613 basename = g_path_get_basename (filename);
2614 tny_mime_part_set_filename (mime_part, basename);
2617 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2618 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2620 info->size == 0, info->size);
2621 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2622 gtk_widget_show_all (priv->attachments_caption);
2623 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2625 g_object_unref (mime_part);
2626 gnome_vfs_file_info_unref (info);
2633 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2636 ModestMsgEditWindowPrivate *priv;
2639 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2642 if (att_list == NULL) {
2643 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2644 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2645 g_object_unref (att_list);
2649 g_object_ref (att_list);
2652 if (tny_list_get_length (att_list) == 0) {
2653 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2655 gboolean dialog_response;
2656 gchar *message = NULL;
2657 gchar *filename = NULL;
2659 if (tny_list_get_length (att_list) == 1) {
2661 iter = tny_list_create_iterator (att_list);
2662 part = (TnyMimePart *) tny_iterator_get_current (iter);
2663 g_object_unref (iter);
2664 if (TNY_IS_MSG (part)) {
2665 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2667 filename = tny_header_dup_subject (header);
2668 g_object_unref (header);
2670 if (filename == NULL) {
2671 filename = g_strdup (_("mail_va_no_subject"));
2674 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2676 g_object_unref (part);
2678 filename = g_strdup ("");
2680 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2681 "emev_nc_delete_attachments",
2682 tny_list_get_length (att_list)), filename);
2685 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2689 if (dialog_response != GTK_RESPONSE_OK) {
2690 g_object_unref (att_list);
2694 for (iter = tny_list_create_iterator (att_list);
2695 !tny_iterator_is_done (iter);
2696 tny_iterator_next (iter)) {
2697 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2698 const gchar *att_id;
2699 tny_list_remove (priv->attachments, (GObject *) mime_part);
2701 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2703 if (tny_list_get_length (priv->attachments) == 0)
2704 gtk_widget_hide (priv->attachments_caption);
2705 att_id = tny_mime_part_get_content_id (mime_part);
2707 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2709 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2710 g_object_unref (mime_part);
2712 g_object_unref (iter);
2715 g_object_unref (att_list);
2717 /* if the last attachment has been removed, focus the Subject: field */
2718 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2719 gtk_widget_grab_focus (priv->subject_field);
2723 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2726 ModestMsgEditWindowPrivate *priv;
2727 GdkColor *new_color;
2728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2730 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2731 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2734 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2736 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2738 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2740 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2745 font_size_clicked (GtkToolButton *button,
2746 ModestMsgEditWindow *window)
2748 ModestMsgEditWindowPrivate *priv;
2749 GtkWidget *selector, *dialog;
2751 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2753 selector = hildon_touch_selector_new ();
2754 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2755 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2757 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2758 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2759 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2761 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2765 WPTextBufferFormat format;
2767 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2769 memset (&format, 0, sizeof (format));
2770 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2772 format.cs.font_size = TRUE;
2773 format.cs.text_position = TRUE;
2774 format.cs.font = TRUE;
2775 format.font_size = new_index;
2776 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2778 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2779 GINT_TO_POINTER (new_index)))
2780 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2782 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2783 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2784 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2785 size_text, "</span>", NULL);
2787 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2791 gtk_widget_destroy (dialog);
2793 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2798 font_face_clicked (GtkToolButton *button,
2799 ModestMsgEditWindow *window)
2801 ModestMsgEditWindowPrivate *priv;
2802 GtkWidget *selector, *dialog;
2803 GtkCellRenderer *renderer;
2805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2807 selector = hildon_touch_selector_new ();
2808 renderer = gtk_cell_renderer_text_new ();
2809 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2810 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2811 renderer, "family", 0, "text", 0, NULL);
2812 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2814 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2815 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2816 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2818 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2819 gint new_font_index;
2823 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2824 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2825 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2829 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2831 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2832 GINT_TO_POINTER(new_font_index)))
2833 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2835 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2836 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2842 gtk_tree_path_free (path);
2845 gtk_widget_destroy (dialog);
2847 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2852 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2855 ModestMsgEditWindowPrivate *priv = NULL;
2856 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2859 if (!priv->update_caption_visibility)
2862 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2864 gtk_widget_show (priv->cc_caption);
2866 gtk_widget_hide (priv->cc_caption);
2868 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2872 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2875 ModestMsgEditWindowPrivate *priv = NULL;
2876 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2878 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2879 if (!priv->update_caption_visibility)
2882 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2884 gtk_widget_show (priv->bcc_caption);
2886 gtk_widget_hide (priv->bcc_caption);
2888 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2892 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2893 ModestRecptEditor *editor)
2895 ModestMsgEditWindowPrivate *priv;
2897 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2898 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2900 /* we check for low-mem; in that case, show a warning, and don't allow
2901 * for the addressbook
2903 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2906 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2908 if (editor == NULL) {
2909 GtkWidget *view_focus, *parent;
2910 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2912 /* This code should be kept in sync with ModestRecptEditor. The
2913 textview inside the recpt editor is the one that really gets the
2914 focus. As it's inside a scrolled window, and this one inside the
2915 hbox recpt editor inherits from, we'll need to go up in the
2916 hierarchy to know if the text view is part of the recpt editor
2917 or if it's a different text entry */
2918 parent = gtk_widget_get_parent (view_focus);
2919 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2920 editor = MODEST_RECPT_EDITOR (parent);
2923 editor = MODEST_RECPT_EDITOR (priv->to_field);
2926 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2930 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2932 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2934 modest_msg_edit_window_open_addressbook (window, NULL);
2938 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2939 gboolean show_toolbar)
2941 ModestWindowPrivate *parent_priv;
2942 ModestMsgEditWindowPrivate *priv;
2944 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2945 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2946 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2948 /* We can not just use the code of
2949 modest_msg_edit_window_setup_toolbar because it has a
2950 mixture of both initialization and creation code. */
2952 gint current_format;
2953 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2954 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2955 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2956 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2958 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2961 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2966 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2967 TnyHeaderFlags priority_flags)
2969 ModestMsgEditWindowPrivate *priv;
2970 ModestWindowPrivate *parent_priv;
2972 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2974 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2975 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2977 if (priv->priority_flags != priority_flags) {
2978 GtkAction *priority_action = NULL;
2980 priv->priority_flags = priority_flags;
2982 switch (priority_flags) {
2983 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2984 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2985 MODEST_HEADER_ICON_HIGH,
2986 HILDON_ICON_SIZE_SMALL);
2987 gtk_widget_show (priv->priority_icon);
2988 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2989 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2991 case TNY_HEADER_FLAG_LOW_PRIORITY:
2992 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2993 MODEST_HEADER_ICON_LOW,
2994 HILDON_ICON_SIZE_SMALL);
2995 gtk_widget_show (priv->priority_icon);
2996 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2997 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3000 gtk_widget_hide (priv->priority_icon);
3001 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3002 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3005 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3006 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3008 gtk_widget_queue_resize (priv->subject_box);
3012 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3015 ModestMsgEditWindowPrivate *priv;
3016 ModestWindowPrivate *parent_priv;
3017 gint current_format;
3019 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3021 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3022 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3024 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3025 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3027 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3029 if (parent_priv->toolbar) {
3030 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3031 gtk_widget_hide (parent_priv->toolbar);
3033 gtk_widget_show (parent_priv->toolbar);
3037 if (current_format != file_format) {
3038 switch (file_format) {
3039 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3040 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3041 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3043 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3047 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3048 response = gtk_dialog_run (GTK_DIALOG (dialog));
3049 gtk_widget_destroy (dialog);
3050 if (response == GTK_RESPONSE_OK) {
3051 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3052 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3054 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3055 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3060 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3061 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3062 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3067 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3070 ModestMsgEditWindowPrivate *priv;
3071 WPTextBufferFormat oldfmt, fmt;
3072 gint old_position = 0;
3076 GdkColor *color = NULL;
3077 gboolean bold, bold_set, italic, italic_set;
3078 gboolean underline, underline_set;
3079 gboolean strikethrough, strikethrough_set;
3080 gboolean position_set;
3081 gboolean font_size_set, font_set, color_set;
3084 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3087 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3088 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3089 GTK_WINDOW(dialog), GTK_WINDOW (window));
3091 /* First we get the currently selected font information */
3092 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3094 switch (oldfmt.text_position) {
3095 case TEXT_POSITION_NORMAL:
3098 case TEXT_POSITION_SUPERSCRIPT:
3106 g_object_set (G_OBJECT (dialog),
3107 "bold", oldfmt.bold != FALSE,
3108 "bold-set", !oldfmt.cs.bold,
3109 "underline", oldfmt.underline != FALSE,
3110 "underline-set", !oldfmt.cs.underline,
3111 "italic", oldfmt.italic != FALSE,
3112 "italic-set", !oldfmt.cs.italic,
3113 "strikethrough", oldfmt.strikethrough != FALSE,
3114 "strikethrough-set", !oldfmt.cs.strikethrough,
3115 "color", &oldfmt.color,
3116 "color-set", !oldfmt.cs.color,
3117 "size", wp_font_size[oldfmt.font_size],
3118 "size-set", !oldfmt.cs.font_size,
3119 "position", old_position,
3120 "position-set", !oldfmt.cs.text_position,
3121 "family", wp_get_font_name (oldfmt.font),
3122 "family-set", !oldfmt.cs.font,
3125 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3126 GTK_WINDOW (dialog), GTK_WINDOW (window));
3127 gtk_widget_show_all (dialog);
3128 priv->font_dialog = dialog;
3129 response = gtk_dialog_run (GTK_DIALOG (dialog));
3130 priv->font_dialog = NULL;
3131 if (response == GTK_RESPONSE_OK) {
3133 g_object_get( dialog,
3135 "bold-set", &bold_set,
3136 "underline", &underline,
3137 "underline-set", &underline_set,
3139 "italic-set", &italic_set,
3140 "strikethrough", &strikethrough,
3141 "strikethrough-set", &strikethrough_set,
3143 "color-set", &color_set,
3145 "size-set", &font_size_set,
3146 "family", &font_name,
3147 "family-set", &font_set,
3148 "position", &position,
3149 "position-set", &position_set,
3154 if (response == GTK_RESPONSE_OK) {
3155 memset(&fmt, 0, sizeof(fmt));
3161 fmt.italic = italic;
3162 fmt.cs.italic = TRUE;
3164 if (underline_set) {
3165 fmt.underline = underline;
3166 fmt.cs.underline = TRUE;
3168 if (strikethrough_set) {
3169 fmt.strikethrough = strikethrough;
3170 fmt.cs.strikethrough = TRUE;
3175 ? TEXT_POSITION_NORMAL
3176 : ( ( position == 1 )
3177 ? TEXT_POSITION_SUPERSCRIPT
3178 : TEXT_POSITION_SUBSCRIPT );
3179 fmt.cs.text_position = TRUE;
3180 fmt.font_size = oldfmt.font_size;
3184 fmt.cs.color = TRUE;
3187 fmt.font = wp_get_font_index(font_name,
3192 if (font_size_set) {
3193 fmt.cs.font_size = TRUE;
3194 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3196 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3197 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3199 gtk_widget_destroy (dialog);
3201 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3205 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3207 ModestMsgEditWindowPrivate *priv;
3209 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3210 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3212 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3214 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3215 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3219 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3221 ModestMsgEditWindowPrivate *priv;
3223 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3224 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3226 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3228 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3229 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3234 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 priv->can_undo = can_undo;
3242 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3244 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3246 priv->can_redo = can_redo;
3250 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3252 ModestMsgEditWindowPrivate *priv;
3253 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3254 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 return priv->can_undo;
3260 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv;
3263 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3264 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3266 return priv->can_redo;
3271 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3274 GtkTextIter match_start, match_end;
3276 if (image_id == NULL)
3279 gtk_text_buffer_get_start_iter (buffer, &iter);
3281 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3282 GSList *tags = gtk_text_iter_get_tags (&match_start);
3284 for (node = tags; node != NULL; node = g_slist_next (node)) {
3285 GtkTextTag *tag = (GtkTextTag *) node->data;
3286 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3287 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3288 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3290 offset = gtk_text_iter_get_offset (&match_start);
3291 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3292 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3296 gtk_text_iter_forward_char (&iter);
3301 message_is_empty (ModestMsgEditWindow *window)
3303 ModestMsgEditWindowPrivate *priv = NULL;
3305 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3306 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3308 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3309 * so we can ignore markup.
3311 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3314 count = gtk_text_buffer_get_char_count (buf);
3320 msg_body_focus (GtkWidget *focus,
3321 GdkEventFocus *event,
3325 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3326 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3327 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3332 recpt_field_changed (GtkTextBuffer *buffer,
3333 ModestMsgEditWindow *editor)
3335 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3336 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3340 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3342 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3343 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3347 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3350 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3351 GtkTextBuffer *buffer;
3353 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3354 gtk_text_buffer_set_modified (buffer, modified);
3355 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3356 gtk_text_buffer_set_modified (buffer, modified);
3357 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3358 gtk_text_buffer_set_modified (buffer, modified);
3359 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3363 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3365 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3366 const char *account_name;
3367 GtkTextBuffer *buffer;
3369 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3370 if (gtk_text_buffer_get_modified (buffer))
3372 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3373 if (gtk_text_buffer_get_modified (buffer))
3375 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3376 if (gtk_text_buffer_get_modified (buffer))
3378 if (gtk_text_buffer_get_modified (priv->text_buffer))
3381 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3382 if (priv->original_mailbox) {
3383 if (!account_name || strcmp (account_name, priv->original_mailbox))
3385 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3396 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3398 ModestMsgEditWindowPrivate *priv = NULL;
3400 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3403 /* check if there's no recipient added */
3404 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3405 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3406 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3407 /* no recipient contents, then select contacts */
3408 modest_msg_edit_window_open_addressbook (window, NULL);
3412 g_object_ref (window);
3413 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3414 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3415 g_object_unref (window);
3418 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3419 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3420 g_object_unref (window);
3423 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3424 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3425 g_object_unref (window);
3429 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3430 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3431 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3432 g_object_unref (window);
3439 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3440 ModestMsgEditWindow *window)
3442 modest_msg_edit_window_offer_attach_file (window);
3446 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3448 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3450 return priv->clipboard_text;
3454 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3456 ModestMsgEditWindow *window)
3458 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3459 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3462 /* It could happen that the window was already closed */
3463 if (!GTK_WIDGET_VISIBLE (window))
3466 g_object_ref (window);
3467 text = gtk_clipboard_wait_for_text (selection_clipboard);
3469 if (priv->clipboard_text != NULL) {
3470 g_free (priv->clipboard_text);
3472 priv->clipboard_text = text;
3474 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3476 g_object_unref (window);
3479 static gboolean clipboard_owner_change_idle (gpointer userdata)
3481 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3482 ModestMsgEditWindowPrivate *priv;
3484 gdk_threads_enter ();
3485 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3488 priv->clipboard_owner_idle = 0;
3489 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3490 gdk_threads_leave ();
3496 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3498 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3499 if (priv->clipboard_owner_idle == 0) {
3500 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3501 clipboard_owner_change_idle,
3502 g_object_ref (window),
3508 subject_field_move_cursor (GtkEntry *entry,
3509 GtkMovementStep step,
3514 /* It could happen that the window was already closed */
3515 if (!GTK_WIDGET_VISIBLE (window))
3518 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3522 update_window_title (ModestMsgEditWindow *window)
3524 ModestMsgEditWindowPrivate *priv = NULL;
3525 const gchar *subject;
3527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3528 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3529 if (subject == NULL || subject[0] == '\0')
3530 subject = _("mail_va_new_email");
3532 gtk_window_set_title (GTK_WINDOW (window), subject);
3538 body_insert_text (GtkTextBuffer *buffer,
3539 GtkTextIter *location,
3542 ModestMsgEditWindow *window)
3544 GtkTextIter end_iter;
3548 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3550 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3552 offset = gtk_text_iter_get_offset (&end_iter);
3553 utf8_len = g_utf8_strlen (text, len);
3555 if (offset + utf8_len > MAX_BODY_LENGTH) {
3556 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3557 if (offset < MAX_BODY_LENGTH)
3562 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3564 /* Prevent endless recursion */
3565 result = g_strndup (text, utf8_end - text);
3566 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3567 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3568 (gpointer) result, (gpointer) (utf8_end - text),
3570 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3574 if (offset + utf8_len > MAX_BODY_LENGTH) {
3575 if (priv->max_chars_banner == NULL) {
3576 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3577 _CS("ckdg_ib_maximum_characters_reached"));
3578 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3584 subject_field_changed (GtkEditable *editable,
3585 ModestMsgEditWindow *window)
3587 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3588 update_window_title (window);
3589 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3590 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3591 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3594 subject_field_insert_text (GtkEditable *editable,
3596 gint new_text_length,
3598 ModestMsgEditWindow *window)
3600 GString *result = g_string_new ("");
3602 gint result_len = 0;
3603 const gchar *entry_text = NULL;
3606 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3607 old_length = g_utf8_strlen (entry_text, -1);
3609 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3610 gunichar c = g_utf8_get_char_validated (current, 8);
3611 /* Invalid unichar, stop */
3617 result = g_string_append_unichar (result, c);
3621 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3622 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3625 /* Prevent endless recursion */
3626 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3627 g_signal_emit_by_name (editable, "insert-text",
3628 (gpointer) result->str, (gpointer) result->len,
3629 (gpointer) position, (gpointer) window);
3630 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3634 if (result_len + old_length > 1000) {
3635 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3636 _CS("ckdg_ib_maximum_characters_reached"));
3638 g_string_free (result, TRUE);
3642 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3645 ModestMsgEditWindowPrivate *priv = NULL;
3647 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3650 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3653 gtk_widget_show_all (priv->find_toolbar);
3654 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3656 gtk_widget_hide_all (priv->find_toolbar);
3657 gtk_widget_grab_focus (priv->msg_body);
3662 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3664 GtkTextIter *match_start,
3665 GtkTextIter *match_end)
3667 GtkTextIter end_iter;
3668 gchar *str_casefold;
3671 gchar *range_casefold;
3674 gboolean result = FALSE;
3681 gtk_text_iter_forward_to_end (&end_iter);
3683 str_casefold = g_utf8_casefold (str, -1);
3684 str_chars_n = strlen (str);
3686 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3687 range_casefold = g_utf8_casefold (range_text, -1);
3688 range_chars_n = strlen (range_casefold);
3690 if (range_chars_n < str_chars_n) {
3691 g_free (str_casefold);
3692 g_free (range_text);
3693 g_free (range_casefold);
3697 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3698 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3699 if (!g_utf8_collate (range_subtext, str_casefold)) {
3700 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3702 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3703 match_start, match_end, NULL)) {
3704 g_warning ("Matched string with collate, but not matched in model");
3706 g_free (found_text);
3708 g_free (range_subtext);
3712 g_free (str_casefold);
3713 g_free (range_text);
3714 g_free (range_casefold);
3721 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3722 ModestMsgEditWindow *window)
3724 gchar *current_search = NULL;
3725 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3727 GtkTextIter selection_start, selection_end;
3728 GtkTextIter match_start, match_end;
3729 gboolean continue_search = FALSE;
3731 if (message_is_empty (window)) {
3732 g_free (priv->last_search);
3733 priv->last_search = NULL;
3734 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3738 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3739 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3740 g_free (current_search);
3741 g_free (priv->last_search);
3742 priv->last_search = NULL;
3743 /* Information banner about empty search */
3744 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3748 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3749 continue_search = TRUE;
3751 g_free (priv->last_search);
3752 priv->last_search = g_strdup (current_search);
3755 if (continue_search) {
3756 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3757 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3758 &match_start, &match_end);
3760 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3762 GtkTextIter buffer_start;
3763 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3764 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3765 &match_start, &match_end);
3767 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3770 /* Mark as selected the string found in search */
3772 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3773 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3774 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3776 g_free (priv->last_search);
3777 priv->last_search = NULL;
3779 g_free (current_search);
3783 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3785 ModestMsgEditWindowPrivate *priv;
3787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3792 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3795 ModestMsgEditWindowPrivate *priv;
3797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3802 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3803 ModestMsgEditWindow *window)
3805 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3809 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3812 ModestMsgEditWindowPrivate *priv;
3813 TnyHeader *header = NULL;
3815 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3816 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3820 if (priv->draft_msg != NULL) {
3821 g_object_unref (priv->draft_msg);
3824 if (draft != NULL) {
3825 g_object_ref (draft);
3826 header = tny_msg_get_header (draft);
3827 if (priv->msg_uid) {
3828 g_free (priv->msg_uid);
3829 priv->msg_uid = NULL;
3831 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3834 priv->draft_msg = draft;
3838 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3839 GtkTextIter *start, GtkTextIter *end,
3842 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3843 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3846 if (tag == NULL) return;
3847 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3848 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3849 replace_with_images (window, priv->images);
3854 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3857 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3859 g_return_if_fail (TNY_IS_MIME_PART (part));
3860 tny_list_prepend (priv->attachments, (GObject *) part);
3861 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3862 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3863 gtk_widget_show_all (priv->attachments_caption);
3864 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3868 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3870 ModestMsgEditWindowPrivate *priv;
3872 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3873 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3875 return priv->msg_uid;
3879 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3880 ModestMsgEditWindowWidgetType widget_type)
3882 ModestMsgEditWindowPrivate *priv;
3884 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3887 switch (widget_type) {
3888 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3889 return priv->msg_body;
3891 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3892 return priv->to_field;
3894 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3895 return priv->cc_field;
3897 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3898 return priv->bcc_field;
3900 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3901 return priv->subject_field;
3903 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3904 return priv->attachments_view;
3912 remove_tags (WPTextBuffer *buffer)
3914 GtkTextIter start, end;
3916 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3917 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3919 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3923 on_account_removed (TnyAccountStore *account_store,
3924 TnyAccount *account,
3927 /* Do nothing if it's a store account, because we use the
3928 transport to send the messages */
3929 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3930 const gchar *parent_acc = NULL;
3931 const gchar *our_acc = NULL;
3933 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3934 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3935 /* Close this window if I'm showing a message of the removed account */
3936 if (strcmp (parent_acc, our_acc) == 0)
3937 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3941 static void update_signature (ModestMsgEditWindow *self,
3942 const gchar *old_account,
3943 const gchar *new_account)
3945 ModestMsgEditWindowPrivate *priv;
3946 gboolean has_old_signature, has_new_signature;
3948 GtkTextIter match_start, match_end;
3949 ModestAccountMgr *mgr;
3951 gchar *full_signature;
3953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3955 gtk_text_buffer_begin_user_action (priv->text_buffer);
3957 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3958 mgr = modest_runtime_get_account_mgr ();
3962 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3963 if (has_old_signature) {
3964 full_signature = g_strconcat ("\n--\n", signature, NULL);
3965 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3966 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3968 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3969 &match_start, &match_end, NULL)) {
3972 g_free (full_signature);
3977 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3978 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3979 if (has_new_signature) {
3980 full_signature = g_strconcat ("\n--\n", signature, NULL);
3981 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3982 g_free (full_signature);
3985 gtk_text_buffer_end_user_action (priv->text_buffer);
3989 from_field_changed (HildonPickerButton *button,
3990 ModestMsgEditWindow *self)
3992 ModestMsgEditWindowPrivate *priv;
3993 gchar *old_account, *new_account;
3995 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3997 old_account = priv->last_from_account;
3998 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3999 new_account = priv->last_from_account;
4001 update_signature (self, old_account, new_account);
4005 typedef struct _MessageSettingsHelper {
4006 ModestMsgEditWindow *window;
4007 GSList *priority_group;
4008 GSList *format_group;
4009 GtkToggleButton *current_priority;
4010 GtkToggleButton *current_format;
4011 } MessageSettingsHelper;
4014 on_priority_toggle (GtkToggleButton *button,
4015 MessageSettingsHelper *helper)
4018 ModestMsgEditWindowPrivate *priv;
4020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4021 if (gtk_toggle_button_get_active (button)) {
4023 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4024 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4025 if ((node_button != button) &&
4026 gtk_toggle_button_get_active (node_button)) {
4027 gtk_toggle_button_set_active (node_button, FALSE);
4030 helper->current_priority = button;
4032 gboolean found = FALSE;
4033 /* If no one is active, activate it again */
4034 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4035 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4036 if (gtk_toggle_button_get_active (node_button)) {
4042 gtk_toggle_button_set_active (button, TRUE);
4048 on_format_toggle (GtkToggleButton *button,
4049 MessageSettingsHelper *helper)
4052 ModestMsgEditWindowPrivate *priv;
4054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4055 if (gtk_toggle_button_get_active (button)) {
4057 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4058 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4059 if ((node_button != button) &&
4060 gtk_toggle_button_get_active (node_button)) {
4061 gtk_toggle_button_set_active (node_button, FALSE);
4064 helper->current_format = button;
4066 gboolean found = FALSE;
4067 /* If no one is active, activate it again */
4068 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4069 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4070 if (gtk_toggle_button_get_active (node_button)) {
4076 gtk_toggle_button_set_active (button, TRUE);
4083 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4088 GtkWidget *priority_hbox;
4089 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4090 GtkWidget *captioned;
4091 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4092 GtkWidget *format_hbox;
4093 GtkWidget *html_toggle, *text_toggle;
4094 ModestMsgEditWindowPrivate *priv;
4095 MessageSettingsHelper helper = {0,};
4097 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4098 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4099 helper.window = window;
4100 helper.priority_group = NULL;
4101 helper.format_group = NULL;
4103 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4104 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4106 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4107 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4108 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4109 vbox = gtk_vbox_new (FALSE, 0);
4110 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4111 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4112 gtk_container_add (GTK_CONTAINER (align), vbox);
4113 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4114 gtk_widget_show (align);
4115 gtk_widget_show (vbox);
4117 /* Priority toggles */
4118 priority_hbox = gtk_hbox_new (TRUE, 0);
4119 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4120 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4121 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4122 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4123 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4124 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4125 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4126 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4127 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4128 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4129 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4130 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4131 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4132 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4133 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4134 gtk_widget_show_all (priority_hbox);
4135 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4136 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4137 gtk_widget_show (captioned);
4138 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4140 /* format toggles */
4141 format_hbox = gtk_hbox_new (TRUE, 0);
4142 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4143 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4144 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4145 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4146 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4147 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4148 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4149 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4150 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4151 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4152 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4153 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4154 gtk_widget_show_all (format_hbox);
4155 gtk_widget_show (format_hbox);
4156 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4159 g_object_unref (title_sizegroup);
4160 g_object_unref (value_sizegroup);
4162 /* Set current values */
4163 switch (priv->priority_flags) {
4164 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4165 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4166 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4168 case TNY_HEADER_FLAG_LOW_PRIORITY:
4169 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4170 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4173 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4174 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4178 switch (modest_msg_edit_window_get_format (window)) {
4179 case MODEST_MSG_EDIT_FORMAT_TEXT:
4180 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4181 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4183 case MODEST_MSG_EDIT_FORMAT_HTML:
4185 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4186 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4190 /* Signal connects */
4191 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4192 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4193 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4194 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4195 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4197 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4198 GTK_WINDOW (dialog), GTK_WINDOW (window));
4200 /* Save settings if the user clicked on done */
4201 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4202 TnyHeaderFlags flags;
4203 ModestMsgEditFormat old_format, new_format;
4205 /* Set priority flags */
4206 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4207 if (priv->priority_flags != flags)
4208 modest_msg_edit_window_set_priority_flags (window, flags);
4210 /* Set edit format */
4211 old_format = modest_msg_edit_window_get_format (window);
4212 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4213 if (old_format != new_format) {
4214 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4215 modest_msg_edit_window_set_file_format (window, file_format);
4219 gtk_widget_destroy (dialog);
4220 g_slist_free (helper.priority_group);
4224 on_message_settings (GtkAction *action,
4225 ModestMsgEditWindow *window)
4227 modest_msg_edit_window_show_msg_settings_dialog (window);
4231 on_cc_button_toggled (HildonCheckButton *button,
4232 ModestMsgEditWindow *window)
4234 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4236 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4237 hildon_check_button_get_active (button));
4241 on_bcc_button_toggled (HildonCheckButton *button,
4242 ModestMsgEditWindow *window)
4244 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4246 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4247 hildon_check_button_get_active (button));
4251 setup_menu (ModestMsgEditWindow *self)
4253 ModestMsgEditWindowPrivate *priv = NULL;
4255 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4257 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4259 /* Settings menu buttons */
4260 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4261 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4263 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4264 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4265 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4267 priv->cc_button = hildon_check_button_new (0);
4268 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4269 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4271 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4273 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4274 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4275 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4276 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4278 priv->bcc_button = hildon_check_button_new (0);
4279 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4280 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4282 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4284 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4285 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4286 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4287 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4289 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4290 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4291 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4292 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4293 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4295 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4296 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4297 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4298 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4299 APP_MENU_CALLBACK (on_message_settings),
4301 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4302 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4307 emit_open_addressbook (GtkButton *button,
4308 ModestRecptEditor *editor)
4310 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4314 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4315 const gchar *label, GtkWidget *control)
4317 GtkWidget *abook_button;
4320 GtkWidget *label_widget;
4322 box = gtk_hbox_new (FALSE, 0);
4324 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4325 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4327 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4328 label_widget = gtk_label_new (label);
4329 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4330 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4332 gtk_container_add (GTK_CONTAINER (align), abook_button);
4333 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4334 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4335 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4336 if (title_size_group)
4337 gtk_size_group_add_widget (title_size_group, label_widget);
4338 if (value_size_group)
4339 gtk_size_group_add_widget (value_size_group, control);
4341 g_signal_connect (G_OBJECT (abook_button), "clicked",
4342 G_CALLBACK (emit_open_addressbook), control);
4348 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4350 ModestMsgEditWindowPrivate *priv = NULL;
4352 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4354 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4355 priv->max_chars_banner = NULL;