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 DEBUG_BUFFER (WPTextBuffer *buffer)
196 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
198 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
199 while (!gtk_text_iter_is_end (&iter)) {
200 GString *output = g_string_new ("");
201 GSList *toggled_tags;
204 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
205 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
206 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
207 GtkTextTag *tag = (GtkTextTag *) node->data;
209 g_object_get (G_OBJECT (tag), "name", &name, NULL);
210 output = g_string_append (output, name);
211 g_string_append (output, " ");
213 output = g_string_append (output, "] OPENED [ ");
214 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
215 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
216 GtkTextTag *tag = (GtkTextTag *) node->data;
218 g_object_get (G_OBJECT (tag), "name", &name, NULL);
219 output = g_string_append (output, name);
220 g_string_append (output, " ");
222 output = g_string_append (output, "]\n");
223 g_message ("%s", output->str);
224 g_string_free (output, TRUE);
225 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
227 g_message ("END BUFFER");
231 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
232 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
236 /* static gboolean */
237 /* on_key_pressed (GtkWidget *self, */
238 /* GdkEventKey *event, */
239 /* gpointer user_data); */
241 /* list my signals */
248 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
249 struct _ModestMsgEditWindowPrivate {
251 GtkWidget *header_box;
253 ModestPairList *from_field_protos;
254 GtkWidget *from_field;
255 gchar *last_from_account;
256 gchar *original_account_name;
261 gchar *original_mailbox;
265 GtkWidget *bcc_field;
266 GtkWidget *subject_field;
267 GtkWidget *attachments_view;
268 GtkWidget *priority_icon;
269 GtkWidget *subject_box;
270 GtkWidget *send_button;
272 GtkWidget *cc_caption;
273 GtkWidget *bcc_caption;
274 gboolean update_caption_visibility;
275 GtkWidget *attachments_caption;
277 GtkTextBuffer *text_buffer;
279 GtkWidget *font_size_toolitem;
280 GtkWidget *font_face_toolitem;
281 GtkWidget *font_color_button;
282 GtkWidget *font_color_toolitem;
283 GSList *font_items_group;
284 GtkTreeModel *faces_model;
285 gint current_face_index;
286 GtkWidget *font_tool_button_label;
287 GtkTreeModel *sizes_model;
288 gint current_size_index;
289 GtkWidget *size_tool_button_label;
291 GtkWidget *find_toolbar;
294 GtkWidget *font_dialog;
297 guint correct_scroll_idle;
298 guint scroll_drag_timeout_id;
302 TnyList *attachments;
307 TnyHeaderFlags priority_flags;
309 gboolean can_undo, can_redo;
310 gulong clipboard_change_handler_id;
311 gulong default_clipboard_change_handler_id;
312 gulong account_removed_handler_id;
313 guint clipboard_owner_idle;
314 gchar *clipboard_text;
323 GtkWidget *cc_button;
324 GtkWidget *bcc_button;
327 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
328 MODEST_TYPE_MSG_EDIT_WINDOW, \
329 ModestMsgEditWindowPrivate))
331 static GtkWindowClass *parent_class = NULL;
333 /* uncomment the following if you have defined any signals */
334 /* static guint signals[LAST_SIGNAL] = {0}; */
337 modest_msg_edit_window_get_type (void)
339 static GType my_type = 0;
341 static const GTypeInfo my_info = {
342 sizeof(ModestMsgEditWindowClass),
343 NULL, /* base init */
344 NULL, /* base finalize */
345 (GClassInitFunc) modest_msg_edit_window_class_init,
346 NULL, /* class finalize */
347 NULL, /* class data */
348 sizeof(ModestMsgEditWindow),
350 (GInstanceInitFunc) modest_msg_edit_window_init,
353 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
354 "ModestMsgEditWindow",
362 save_state (ModestWindow *self)
364 modest_widget_memory_save (modest_runtime_get_conf(),
365 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
370 restore_settings (ModestMsgEditWindow *self)
372 ModestConf *conf = NULL;
374 conf = modest_runtime_get_conf ();
376 /* Dim at start clipboard actions */
377 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
382 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
384 GObjectClass *gobject_class;
385 ModestWindowClass *modest_window_class;
386 gobject_class = (GObjectClass*) klass;
387 modest_window_class = (ModestWindowClass*) klass;
389 parent_class = g_type_class_peek_parent (klass);
390 gobject_class->finalize = modest_msg_edit_window_finalize;
392 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
393 modest_window_class->save_state_func = save_state;
394 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
396 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
400 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
402 ModestMsgEditWindowPrivate *priv;
403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
405 priv->msg_body = NULL;
406 priv->from_field = NULL;
407 priv->to_field = NULL;
408 priv->cc_field = NULL;
409 priv->bcc_field = NULL;
410 priv->subject_field = NULL;
411 priv->attachments = TNY_LIST (tny_simple_list_new ());
412 priv->images = TNY_LIST (tny_simple_list_new ());
413 priv->images_size = 0;
414 priv->images_count = 0;
417 priv->cc_caption = NULL;
418 priv->bcc_caption = NULL;
419 priv->update_caption_visibility = FALSE;
421 priv->priority_flags = 0;
423 priv->find_toolbar = NULL;
424 priv->last_search = NULL;
426 priv->draft_msg = NULL;
427 priv->outbox_msg = NULL;
428 priv->msg_uid = NULL;
430 priv->can_undo = FALSE;
431 priv->can_redo = FALSE;
432 priv->clipboard_change_handler_id = 0;
433 priv->default_clipboard_change_handler_id = 0;
434 priv->account_removed_handler_id = 0;
435 priv->clipboard_owner_idle = 0;
436 priv->clipboard_text = NULL;
439 priv->scroll_drag_timeout_id = 0;
440 priv->correct_scroll_idle = 0;
441 priv->last_upper = 0.0;
443 priv->font_dialog = NULL;
444 priv->app_menu = NULL;
446 priv->references = NULL;
447 priv->in_reply_to = NULL;
449 if (!is_wp_text_buffer_started) {
450 is_wp_text_buffer_started = TRUE;
451 wp_text_buffer_library_init ();
456 hildon_program_add_window (hildon_program_get_instance(),
461 multimailbox_get_default_mailbox (const gchar *account_name)
463 gchar *transport_account;
464 gchar *result = NULL;
466 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
468 TNY_ACCOUNT_TYPE_TRANSPORT);
469 if (transport_account) {
471 ModestProtocolRegistry *registry;
473 registry = modest_runtime_get_protocol_registry ();
475 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
476 MODEST_ACCOUNT_PROTO, TRUE);
478 ModestProtocol *protocol =
479 modest_protocol_registry_get_protocol_by_name (registry,
480 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
482 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
483 ModestPairList *pair_list;
485 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
488 ModestPair *pair = (ModestPair *) pair_list->data;
489 result = g_strdup ((const gchar *) pair->first);
490 modest_pair_list_free (pair_list);
501 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
503 static ModestPairList*
504 get_transports (void)
506 GSList *transports = NULL;
508 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
509 GSList *accounts = modest_account_mgr_account_names (account_mgr,
510 TRUE /* only enabled accounts. */);
512 GSList *cursor = accounts;
514 gchar *account_name = cursor->data;
517 gchar *transport_account;
518 gboolean multi_mailbox = FALSE;
519 ModestProtocol *protocol = NULL;
521 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
523 transport_account = modest_account_mgr_get_server_account_name
524 (modest_runtime_get_account_mgr (),
526 TNY_ACCOUNT_TYPE_TRANSPORT);
527 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
528 ModestPairList *pair_list;
529 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
532 transports = g_slist_concat (transports, pair_list);
533 multi_mailbox = TRUE;
538 if (!multi_mailbox) {
539 gchar *from_string = NULL;
541 from_string = modest_account_mgr_get_from_string (account_mgr,
543 if (from_string && account_name) {
544 gchar *name = account_name;
545 ModestPair *pair = modest_pair_new ((gpointer) name,
546 (gpointer) from_string , TRUE);
547 transports = g_slist_prepend (transports, pair);
552 cursor = cursor->next;
554 g_slist_free (accounts); /* only free the accounts, not the elements,
555 * because they are used in the pairlist */
559 static void window_focus (GtkWindow *window,
563 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
567 scroll_drag_timeout (gpointer userdata)
569 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
570 ModestMsgEditWindowPrivate *priv;
572 /* It could happen that the window was already closed */
573 if (!GTK_WIDGET_VISIBLE (win))
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
578 correct_scroll_without_drag_check (win, TRUE);
580 priv->scroll_drag_timeout_id = 0;
586 correct_scroll_without_drag_check_idle (gpointer userdata)
588 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
589 ModestMsgEditWindowPrivate *priv;
591 GdkRectangle rectangle;
592 gint offset_min, offset_max;
596 /* It could happen that the window was already closed */
597 if (!GTK_WIDGET_VISIBLE (w))
600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
602 insert = gtk_text_buffer_get_insert (priv->text_buffer);
603 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
605 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
606 offset_min = priv->msg_body->allocation.y + rectangle.y;
607 offset_max = offset_min + rectangle.height;
609 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
610 offset_min = MAX (offset_min - 48, 0);
611 offset_max = MIN (offset_max + 48, vadj->upper);
613 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
615 priv->correct_scroll_idle = 0;
620 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
626 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
629 if (priv->correct_scroll_idle > 0) {
633 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
634 (GSourceFunc) correct_scroll_without_drag_check_idle,
640 correct_scroll (ModestMsgEditWindow *w)
642 ModestMsgEditWindowPrivate *priv;
644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
645 if (gtk_grab_get_current () == priv->msg_body) {
646 if (priv->scroll_drag_timeout_id == 0) {
647 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
649 (GSourceFunc) scroll_drag_timeout,
656 correct_scroll_without_drag_check (w, TRUE);
660 text_buffer_end_user_action (GtkTextBuffer *buffer,
661 ModestMsgEditWindow *userdata)
664 correct_scroll (userdata);
668 text_buffer_mark_set (GtkTextBuffer *buffer,
671 ModestMsgEditWindow *userdata)
673 gtk_text_buffer_begin_user_action (buffer);
674 gtk_text_buffer_end_user_action (buffer);
678 cut_clipboard_check (GtkTextView *text_view,
681 GtkTextBuffer *buffer;
683 buffer = gtk_text_view_get_buffer (text_view);
684 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
685 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
690 copy_clipboard_check (GtkTextView *text_view,
693 GtkTextBuffer *buffer;
695 buffer = gtk_text_view_get_buffer (text_view);
696 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
697 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
702 attachment_deleted (ModestAttachmentsView *attachments_view,
705 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
710 connect_signals (ModestMsgEditWindow *obj)
712 ModestMsgEditWindowPrivate *priv;
714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
716 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
717 G_CALLBACK (text_buffer_refresh_attributes), obj);
718 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
719 G_CALLBACK (text_buffer_can_undo), obj);
720 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
721 G_CALLBACK (text_buffer_can_redo), obj);
722 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
723 G_CALLBACK (body_changed), obj);
724 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
725 G_CALLBACK (body_insert_text), obj);
726 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
727 G_CALLBACK (body_changed), obj);
728 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
729 G_CALLBACK (text_buffer_end_user_action), obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
731 G_CALLBACK (text_buffer_mark_set), obj);
732 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
733 G_CALLBACK (text_buffer_apply_tag), obj);
734 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
735 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
736 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
737 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
738 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
739 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
741 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
742 G_CALLBACK (from_field_changed), obj);
744 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
745 G_CALLBACK (msg_body_focus), obj);
746 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
747 G_CALLBACK (msg_body_focus), obj);
748 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
749 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
750 "changed", G_CALLBACK (recpt_field_changed), obj);
751 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
752 "changed", G_CALLBACK (recpt_field_changed), obj);
753 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
754 "changed", G_CALLBACK (recpt_field_changed), obj);
755 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
756 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
757 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
759 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
760 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
762 priv->clipboard_change_handler_id =
763 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
764 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
765 priv->default_clipboard_change_handler_id =
766 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
767 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
769 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
770 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
771 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
775 init_wp_text_view_style ()
777 static gboolean initialized = FALSE;
780 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
786 init_window (ModestMsgEditWindow *obj)
788 GtkWidget *to_caption, *subject_caption;
789 GtkWidget *main_vbox;
790 ModestMsgEditWindowPrivate *priv;
791 GtkActionGroup *action_group;
792 ModestWindowPrivate *parent_priv;
793 GdkPixbuf *window_icon = NULL;
794 GError *error = NULL;
796 GtkSizeGroup *title_size_group;
797 GtkSizeGroup *value_size_group;
798 GtkWidget *window_box;
799 GtkWidget *window_align;
800 #if (GTK_MINOR_VERSION >= 10)
801 GdkAtom deserialize_type;
803 GtkWidget *from_send_hbox;
804 GtkWidget *send_icon;
805 GtkWidget *attachments_label;
807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
808 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
810 parent_priv->ui_manager = gtk_ui_manager_new();
811 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
812 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
814 /* Add common actions */
815 gtk_action_group_add_actions (action_group,
816 modest_msg_edit_action_entries,
817 G_N_ELEMENTS (modest_msg_edit_action_entries),
819 gtk_action_group_add_actions (action_group,
820 hildon2_msg_edit_action_entries,
821 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
823 gtk_action_group_add_toggle_actions (action_group,
824 modest_msg_edit_toggle_action_entries,
825 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
827 gtk_action_group_add_radio_actions (action_group,
828 modest_msg_edit_alignment_radio_action_entries,
829 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
831 G_CALLBACK (modest_ui_actions_on_change_justify),
833 gtk_action_group_add_radio_actions (action_group,
834 modest_msg_edit_priority_action_entries,
835 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
837 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
839 gtk_action_group_add_radio_actions (action_group,
840 modest_msg_edit_file_format_action_entries,
841 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
842 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
843 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
845 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
846 g_object_unref (action_group);
848 /* Load the UI definition */
849 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
852 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
853 g_clear_error (&error);
856 /* Add accelerators */
857 gtk_window_add_accel_group (GTK_WINDOW (obj),
858 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
860 parent_priv->menubar = NULL;
862 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
863 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
865 /* Note: This ModestPairList* must exist for as long as the picker
866 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
867 * so it can't know how to manage its memory. */
868 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
869 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
871 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
872 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
873 _("mail_va_from"), priv->from_field);
874 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
875 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
876 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
878 priv->to_field = modest_recpt_editor_new ();
879 priv->cc_field = modest_recpt_editor_new ();
880 priv->bcc_field = modest_recpt_editor_new ();
881 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
882 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
883 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
884 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
885 priv->priority_icon = gtk_image_new ();
886 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
887 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
888 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
889 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
890 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
891 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
892 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
893 priv->attachments_view = modest_attachments_view_new (NULL);
894 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
895 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
897 priv->header_box = gtk_vbox_new (FALSE, 0);
899 to_caption = _create_addressbook_box
900 (title_size_group, value_size_group,
901 _("mail_va_to"), priv->to_field);
902 priv->cc_caption = _create_addressbook_box
903 (title_size_group, value_size_group,
904 _("mail_va_cc"), priv->cc_field);
905 priv->bcc_caption = _create_addressbook_box
906 (title_size_group, value_size_group,
907 _("mail_va_hotfix1"), priv->bcc_field);
908 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
909 _("mail_va_subject"), FALSE, priv->subject_box);
910 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
911 _("mail_va_attachment"),
913 priv->attachments_view,
914 HILDON_SIZE_AUTO_WIDTH |
915 HILDON_SIZE_AUTO_HEIGHT);
916 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
917 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
920 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
921 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
922 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
923 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
925 g_object_unref (title_size_group);
926 g_object_unref (value_size_group);
928 from_send_hbox = gtk_hbox_new (FALSE, 0);
929 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
930 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
932 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
933 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
934 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
935 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
936 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
937 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
938 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
940 init_wp_text_view_style ();
942 priv->msg_body = modest_wp_text_view_new ();
945 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
946 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
947 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
948 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
949 #if (GTK_MINOR_VERSION >= 10)
950 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
951 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
953 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
954 deserialize_type, TRUE);
956 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
958 priv->find_toolbar = hildon_find_toolbar_new (NULL);
959 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
961 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
963 priv->pannable = hildon_pannable_area_new ();
965 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
967 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
968 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
969 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
971 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
972 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
973 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
975 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
976 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
978 window_box = gtk_vbox_new (FALSE, 0);
979 gtk_container_add (GTK_CONTAINER(obj), window_box);
981 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
983 /* Set window icon */
984 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
986 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
987 g_object_unref (window_icon);
992 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
994 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
996 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
997 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
998 priv->clipboard_change_handler_id))
999 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1000 priv->clipboard_change_handler_id);
1001 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1002 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1003 priv->default_clipboard_change_handler_id))
1004 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1005 priv->default_clipboard_change_handler_id);
1007 if (priv->account_removed_handler_id &&
1008 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1009 priv->account_removed_handler_id))
1010 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1011 priv->account_removed_handler_id);
1015 modest_msg_edit_window_finalize (GObject *obj)
1017 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1019 /* Sanity check: shouldn't be needed, the window mgr should
1020 call this function before */
1021 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1023 if (priv->font_dialog != NULL) {
1024 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1027 if (priv->clipboard_text != NULL) {
1028 g_free (priv->clipboard_text);
1029 priv->clipboard_text = NULL;
1032 if (priv->draft_msg != NULL) {
1033 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1034 if (TNY_IS_HEADER (header)) {
1035 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1036 modest_window_mgr_unregister_header (mgr, header);
1038 g_object_unref (priv->draft_msg);
1039 priv->draft_msg = NULL;
1041 if (priv->outbox_msg != NULL) {
1042 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1043 if (TNY_IS_HEADER (header)) {
1044 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1045 modest_window_mgr_unregister_header (mgr, header);
1047 g_object_unref (priv->outbox_msg);
1048 priv->outbox_msg = NULL;
1050 if (priv->correct_scroll_idle > 0) {
1051 g_source_remove (priv->correct_scroll_idle);
1052 priv->correct_scroll_idle = 0;
1054 if (priv->scroll_drag_timeout_id > 0) {
1055 g_source_remove (priv->scroll_drag_timeout_id);
1056 priv->scroll_drag_timeout_id = 0;
1058 if (priv->clipboard_owner_idle > 0) {
1059 g_source_remove (priv->clipboard_owner_idle);
1060 priv->clipboard_owner_idle = 0;
1062 if (priv->original_account_name)
1063 g_free (priv->original_account_name);
1064 if (priv->original_mailbox)
1065 g_free (priv->original_mailbox);
1066 g_free (priv->msg_uid);
1067 g_free (priv->last_search);
1068 g_free (priv->references);
1069 g_free (priv->in_reply_to);
1070 g_object_unref (priv->faces_model);
1071 g_object_unref (priv->sizes_model);
1072 g_object_unref (priv->attachments);
1073 g_object_unref (priv->images);
1075 /* This had to stay alive for as long as the picker that used it: */
1076 modest_pair_list_free (priv->from_field_protos);
1078 G_OBJECT_CLASS(parent_class)->finalize (obj);
1082 pixbuf_size_prepared (GdkPixbufLoader *loader,
1085 ModestMsgEditWindow *self)
1087 gint new_height, new_width;
1090 new_height = height;
1094 if (width > IMAGE_MAX_WIDTH) {
1095 new_height = height * IMAGE_MAX_WIDTH / width;
1096 new_width = IMAGE_MAX_WIDTH;
1099 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1103 pixbuf_from_stream (TnyStream *stream,
1104 const gchar *mime_type,
1105 guint64 *stream_size,
1106 ModestMsgEditWindow *self)
1108 GdkPixbufLoader *loader;
1111 GError *error = NULL;
1115 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1117 if (loader == NULL) {
1122 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1124 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1126 tny_stream_reset (TNY_STREAM (stream));
1127 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1128 unsigned char read_buffer[128];
1130 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1132 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1135 /* Allow some UI responsiveness */
1136 while (gtk_events_pending ())
1137 gtk_main_iteration ();
1139 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1141 gdk_pixbuf_loader_close (loader, &error);
1144 g_error_free (error);
1145 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1147 g_object_ref (pixbuf);
1148 g_object_unref (loader);
1153 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1154 GdkPixbuf *new_pixbuf;
1156 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1157 gdk_pixbuf_get_width (pixbuf);
1158 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1159 g_object_unref (pixbuf);
1160 pixbuf = new_pixbuf;
1164 *stream_size = size;
1170 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1172 ModestMsgEditWindowPrivate *priv;
1175 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1177 g_object_ref (self);
1178 for (iter = tny_list_create_iterator (attachments);
1179 !tny_iterator_is_done (iter);
1180 tny_iterator_next (iter)) {
1181 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1182 const gchar *cid = tny_mime_part_get_content_id (part);
1183 const gchar *mime_type = tny_mime_part_get_content_type (part);
1184 if ((cid != NULL)&&(mime_type != NULL)) {
1185 guint64 stream_size;
1186 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1187 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1190 g_object_unref (stream);
1192 if (pixbuf != NULL) {
1193 priv->images_count ++;
1194 priv->images_size += stream_size;
1195 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1196 g_object_unref (pixbuf);
1199 g_object_unref (part);
1201 g_object_unref (iter);
1202 g_object_unref (self);
1206 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1208 TnyMimePart *parent = NULL;
1209 const gchar *content_type = NULL;
1210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1212 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1214 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1215 parent = g_object_ref (msg);
1216 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1217 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1220 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1221 iter = tny_list_create_iterator (parts);
1222 while (!tny_iterator_is_done (iter)) {
1224 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1225 content_type = tny_mime_part_get_content_type (part);
1226 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1230 g_object_unref (part);
1232 tny_iterator_next (iter);
1234 g_object_unref (iter);
1235 g_object_unref (parts);
1238 if (parent != NULL) {
1239 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1242 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1243 iter = tny_list_create_iterator (parts);
1244 while (!tny_iterator_is_done (iter)) {
1246 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1247 content_type = tny_mime_part_get_content_type (part);
1248 if (content_type && g_str_has_prefix (content_type, "image/")) {
1249 tny_list_prepend (priv->images, (GObject *) part);
1251 g_object_unref (part);
1252 tny_iterator_next (iter);
1254 g_object_unref (iter);
1255 g_object_unref (parts);
1256 g_object_unref (parent);
1261 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1264 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1266 for (iter = tny_list_create_iterator (attachments) ;
1267 !tny_iterator_is_done (iter);
1268 tny_iterator_next (iter)) {
1269 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1270 const gchar *cid = tny_mime_part_get_content_id (part);
1272 char *invalid = NULL;
1273 gint int_cid = strtol (cid, &invalid, 10);
1274 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1275 priv->next_cid = int_cid + 1;
1278 g_object_unref (part);
1280 g_object_unref (iter);
1284 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1287 gchar *to, *cc, *bcc, *subject;
1289 ModestMsgEditWindowPrivate *priv;
1290 ModestWindowPrivate *parent_priv;
1292 TnyHeaderFlags priority_flags;
1293 TnyFolder *msg_folder;
1294 gboolean is_html = FALSE;
1295 gboolean field_view_set;
1297 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1298 g_return_if_fail (TNY_IS_MSG (msg));
1300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1301 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1303 header = tny_msg_get_header (msg);
1304 to = tny_header_dup_to (header);
1305 cc = tny_header_dup_cc (header);
1306 bcc = tny_header_dup_bcc (header);
1307 subject = tny_header_dup_subject (header);
1309 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1310 priority_flags = tny_header_get_priority (header);
1313 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1315 field_view_set = TRUE;
1317 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1318 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1319 gtk_widget_show (priv->cc_caption);
1320 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1321 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1322 gtk_widget_hide (priv->cc_caption);
1323 field_view_set = FALSE;
1325 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1327 field_view_set = TRUE;
1329 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1330 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1331 gtk_widget_show (priv->bcc_caption);
1332 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1333 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1334 gtk_widget_hide (priv->bcc_caption);
1335 field_view_set = FALSE;
1337 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1341 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1342 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1345 update_window_title (self);
1347 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1348 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1350 if ((body == NULL)||(body[0] == '\0')) {
1352 body = modest_text_utils_convert_to_html ("");
1355 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1356 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1359 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1362 /* Add attachments to the view */
1363 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1364 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1365 if (tny_list_get_length (priv->attachments) == 0) {
1366 gtk_widget_hide (priv->attachments_caption);
1368 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1369 gtk_widget_show_all (priv->attachments_caption);
1371 get_related_images (self, msg);
1372 update_next_cid (self, priv->attachments);
1373 update_next_cid (self, priv->images);
1374 replace_with_images (self, priv->images);
1376 if (preserve_is_rich && !is_html) {
1377 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1378 /* Get the default format required from configuration */
1379 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1380 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1383 /* Set the default focus depending on having already a To: field or not */
1384 if ((!to)||(*to == '\0')) {
1385 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1387 gtk_widget_grab_focus (priv->msg_body);
1390 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1392 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1393 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1395 modest_msg_edit_window_set_modified (self, FALSE);
1397 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1398 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1399 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1400 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1402 if (priv->msg_uid) {
1403 g_free (priv->msg_uid);
1404 priv->msg_uid = NULL;
1407 /* we should set a reference to the incoming message if it is a draft */
1408 msg_folder = tny_msg_get_folder (msg);
1410 if (modest_tny_folder_is_local_folder (msg_folder)) {
1411 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1412 if (type == TNY_FOLDER_TYPE_INVALID)
1413 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1415 if (type == TNY_FOLDER_TYPE_DRAFTS)
1416 priv->draft_msg = g_object_ref(msg);
1417 if (type == TNY_FOLDER_TYPE_OUTBOX)
1418 priv->outbox_msg = g_object_ref(msg);
1419 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1421 g_object_unref (msg_folder);
1432 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1434 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1435 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1436 GtkWidget *placeholder;
1437 GtkWidget *tool_item;
1442 GtkWidget *sizes_menu;
1443 GtkWidget *fonts_menu;
1449 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1450 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1451 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1452 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1454 /* Font color placeholder */
1455 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1456 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1459 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1460 priv->font_color_button = hildon_color_button_new ();
1461 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1462 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1463 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1464 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1467 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1468 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1470 G_CALLBACK (modest_msg_edit_window_color_button_change),
1473 /* Font size and face placeholder */
1474 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1475 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1477 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1478 priv->size_tool_button_label = gtk_label_new (NULL);
1479 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1480 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1481 size_text, "</span>", NULL);
1482 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1483 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1485 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1486 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1487 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1488 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1489 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1490 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1491 gtk_widget_set_sensitive (arrow, FALSE);
1492 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1493 sizes_menu = gtk_menu_new ();
1494 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1495 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1498 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1499 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1501 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1505 if (wp_font_size[size_index] == 12)
1506 priv->current_size_index = size_index;
1510 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1511 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1512 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1513 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1514 priv->font_size_toolitem = tool_item;
1517 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1518 priv->font_tool_button_label = gtk_label_new (NULL);
1519 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1520 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1521 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1523 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1524 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1525 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1526 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1527 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1528 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1529 gtk_widget_set_sensitive (arrow, FALSE);
1530 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1531 fonts_menu = gtk_menu_new ();
1532 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1533 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1536 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1538 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1539 0, wp_get_font_name (font_index),
1542 if (font_index == DEFAULT_FONT)
1543 priv->current_face_index = font_index;
1545 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1546 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1547 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1548 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1549 priv->font_face_toolitem = tool_item;
1551 /* Set expand and homogeneous for remaining items */
1552 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1553 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1554 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1555 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1556 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1557 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1559 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1560 will not show the tool items added to the placeholders) */
1561 gtk_widget_show_all (parent_priv->toolbar);
1563 /* Set the no show all *after* showing all items. We do not
1564 want the toolbar to be shown with a show all because it
1565 could go agains the gconf setting regarding showing or not
1566 the toolbar of the editor window */
1567 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1573 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1576 ModestWindowPrivate *parent_priv;
1577 ModestMsgEditWindowPrivate *priv;
1578 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1579 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1580 ModestWindowMgr *mgr = NULL;
1582 g_return_val_if_fail (msg, NULL);
1583 g_return_val_if_fail (account_name, NULL);
1585 mgr = modest_runtime_get_window_mgr ();
1587 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1589 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1590 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1592 /* Menubar. Update the state of some toggles */
1593 priv->from_field_protos = get_transports ();
1594 priv->original_mailbox = NULL;
1595 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1596 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1597 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1598 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1599 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1600 priv->original_mailbox = g_strdup (mailbox);
1601 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1602 /* We set the first mailbox as the active mailbox */
1603 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1604 if (priv->original_mailbox != NULL)
1605 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1606 (gpointer) priv->original_mailbox);
1608 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1609 (gpointer) account_name);
1611 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1613 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1614 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1616 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1617 hildon_touch_selector_get_current_text
1618 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1619 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1620 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1623 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1625 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1627 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1628 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1630 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1632 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1633 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1634 /* Add common dimming rules */
1635 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1636 modest_msg_edit_window_toolbar_dimming_entries,
1637 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1638 MODEST_WINDOW (obj));
1639 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1640 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1641 MODEST_WINDOW (obj));
1642 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1643 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1644 MODEST_WINDOW (obj));
1645 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1646 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1647 MODEST_WINDOW (obj));
1648 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1649 G_CALLBACK (modest_ui_dimming_rules_on_send),
1650 MODEST_WINDOW (obj));
1651 /* Insert dimming rules group for this window */
1652 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1653 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1655 /* Setup app menu */
1656 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1658 /* Checks the dimming rules */
1659 g_object_unref (toolbar_rules_group);
1660 g_object_unref (clipboard_rules_group);
1661 gtk_widget_hide (priv->priority_icon);
1662 gtk_widget_queue_resize (priv->subject_box);
1663 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1665 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1667 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1668 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1669 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1670 priv->update_caption_visibility = TRUE;
1672 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1674 /* Track account-removed signal, this window should be closed
1675 in the case we're creating a mail associated to the account
1677 priv->account_removed_handler_id =
1678 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1680 G_CALLBACK(on_account_removed),
1683 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1685 return (ModestWindow*) obj;
1689 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1691 GString **string_buffer = (GString **) user_data;
1693 *string_buffer = g_string_append (*string_buffer, buffer);
1699 * @result: A new string which should be freed with g_free().
1702 get_formatted_data (ModestMsgEditWindow *edit_window)
1704 ModestMsgEditWindowPrivate *priv;
1705 GString *string_buffer = g_string_new ("");
1707 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1709 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1711 modest_text_utils_hyperlinkify (string_buffer);
1713 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1715 return g_string_free (string_buffer, FALSE);
1720 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1723 const gchar *account_name;
1724 ModestMsgEditWindowPrivate *priv;
1725 TnyIterator *att_iter;
1726 const gchar *picker_active_id;
1728 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1730 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1732 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1733 g_return_val_if_fail (picker_active_id, NULL);
1734 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1736 /* don't free these (except from) */
1737 data = g_slice_new0 (MsgData);
1738 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1739 data->account_name = g_strdup (account_name);
1740 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1741 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1742 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1743 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1744 data->references = g_strdup (priv->references);
1745 data->in_reply_to = g_strdup (priv->in_reply_to);
1746 if (priv->draft_msg) {
1747 data->draft_msg = g_object_ref (priv->draft_msg);
1748 } else if (priv->outbox_msg) {
1749 data->draft_msg = g_object_ref (priv->outbox_msg);
1751 data->draft_msg = NULL;
1754 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1756 gtk_text_buffer_get_bounds (buf, &b, &e);
1757 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1759 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1760 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1762 data->html_body = NULL;
1764 /* deep-copy the data */
1765 att_iter = tny_list_create_iterator (priv->attachments);
1766 data->attachments = NULL;
1767 while (!tny_iterator_is_done (att_iter)) {
1768 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1769 if (!(TNY_IS_MIME_PART(part))) {
1770 g_warning ("strange data in attachment list");
1771 g_object_unref (part);
1772 tny_iterator_next (att_iter);
1775 data->attachments = g_list_append (data->attachments,
1777 tny_iterator_next (att_iter);
1779 g_object_unref (att_iter);
1781 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1782 att_iter = tny_list_create_iterator (priv->images);
1783 data->images = NULL;
1784 while (!tny_iterator_is_done (att_iter)) {
1785 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1787 if (!(TNY_IS_MIME_PART(part))) {
1788 g_warning ("strange data in attachment list");
1789 g_object_unref (part);
1790 tny_iterator_next (att_iter);
1793 cid = tny_mime_part_get_content_id (part);
1795 gchar *image_tag_id;
1796 GtkTextTag *image_tag;
1798 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1799 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1800 g_free (image_tag_id);
1802 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1804 ((gtk_text_iter_has_tag (&iter, image_tag))||
1805 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1806 data->images = g_list_append (data->images,
1807 g_object_ref (part));
1809 g_object_unref (part);
1810 tny_iterator_next (att_iter);
1812 g_object_unref (att_iter);
1814 data->priority_flags = priv->priority_flags;
1821 unref_gobject (GObject *obj, gpointer data)
1823 if (!G_IS_OBJECT(obj))
1825 g_object_unref (obj);
1829 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1832 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1840 g_free (data->from);
1841 g_free (data->subject);
1842 g_free (data->plain_body);
1843 g_free (data->html_body);
1844 g_free (data->account_name);
1845 g_free (data->references);
1846 g_free (data->in_reply_to);
1848 if (data->draft_msg != NULL) {
1849 g_object_unref (data->draft_msg);
1850 data->draft_msg = NULL;
1853 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1854 g_list_free (data->attachments);
1855 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1856 g_list_free (data->images);
1858 g_slice_free (MsgData, data);
1862 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1864 guint64 *parts_size)
1866 ModestMsgEditWindowPrivate *priv;
1868 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1870 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1872 /* TODO: add images */
1873 *parts_size += priv->images_size;
1874 *parts_count += priv->images_count;
1879 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1882 ModestMsgEditWindowPrivate *priv = NULL;
1883 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1887 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1889 return MODEST_MSG_EDIT_FORMAT_HTML;
1891 return MODEST_MSG_EDIT_FORMAT_TEXT;
1895 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1896 ModestMsgEditFormat format)
1898 ModestMsgEditWindowPrivate *priv;
1899 ModestWindowPrivate *parent_priv;
1901 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1903 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1906 case MODEST_MSG_EDIT_FORMAT_HTML:
1907 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1908 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1910 case MODEST_MSG_EDIT_FORMAT_TEXT:
1911 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1912 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1915 g_return_if_reached ();
1919 ModestMsgEditFormatState *
1920 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1922 ModestMsgEditFormatState *format_state = NULL;
1923 ModestMsgEditWindowPrivate *priv;
1924 WPTextBufferFormat *buffer_format;
1926 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1928 buffer_format = g_new0 (WPTextBufferFormat, 1);
1929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1931 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1933 format_state = g_new0 (ModestMsgEditFormatState, 1);
1934 format_state->bold = buffer_format->bold&0x1;
1935 format_state->italics = buffer_format->italic&0x1;
1936 format_state->bullet = buffer_format->bullet&0x1;
1937 format_state->color = buffer_format->color;
1938 format_state->font_size = buffer_format->font_size;
1939 format_state->font_family = wp_get_font_name (buffer_format->font);
1940 format_state->justification = buffer_format->justification;
1941 g_free (buffer_format);
1943 return format_state;
1948 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1949 const ModestMsgEditFormatState *format_state)
1951 ModestMsgEditWindowPrivate *priv;
1952 WPTextBufferFormat *buffer_format;
1953 WPTextBufferFormat *current_format;
1955 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1956 g_return_if_fail (format_state != NULL);
1958 buffer_format = g_new0 (WPTextBufferFormat, 1);
1959 current_format = g_new0 (WPTextBufferFormat, 1);
1961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1962 gtk_widget_grab_focus (priv->msg_body);
1963 buffer_format->bold = (format_state->bold != FALSE);
1964 buffer_format->italic = (format_state->italics != FALSE);
1965 buffer_format->color = format_state->color;
1966 buffer_format->font_size = format_state->font_size;
1967 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1968 buffer_format->justification = format_state->justification;
1969 buffer_format->bullet = format_state->bullet;
1971 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1973 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1974 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1975 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1976 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1977 buffer_format->cs.font = (buffer_format->font != current_format->font);
1978 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1979 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1981 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1982 if (buffer_format->cs.bold) {
1983 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1984 GINT_TO_POINTER (buffer_format->bold&0x1));
1986 if (buffer_format->cs.italic) {
1987 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1988 GINT_TO_POINTER (buffer_format->italic&0x1));
1990 if (buffer_format->cs.color) {
1991 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1992 GINT_TO_POINTER (&(buffer_format->color)));
1994 if (buffer_format->cs.font_size) {
1995 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1996 GINT_TO_POINTER (buffer_format->font_size));
1998 if (buffer_format->cs.justification) {
1999 switch (buffer_format->justification) {
2000 case GTK_JUSTIFY_LEFT:
2001 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2002 GINT_TO_POINTER(TRUE));
2004 case GTK_JUSTIFY_CENTER:
2005 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2006 GINT_TO_POINTER(TRUE));
2008 case GTK_JUSTIFY_RIGHT:
2009 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2010 GINT_TO_POINTER(TRUE));
2017 if (buffer_format->cs.font) {
2018 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2019 GINT_TO_POINTER (buffer_format->font));
2021 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2022 if (buffer_format->cs.bullet) {
2023 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2024 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2026 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2028 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2030 g_free (buffer_format);
2031 g_free (current_format);
2033 /* Check dimming rules */
2034 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2035 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2039 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2041 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2043 ModestWindowPrivate *parent_priv;
2044 ModestMsgEditWindowPrivate *priv;
2046 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2049 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2050 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2051 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2052 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2054 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2055 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2056 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2059 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2061 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2062 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2064 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2065 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2067 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2068 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2071 switch (buffer_format->justification)
2073 case GTK_JUSTIFY_LEFT:
2074 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2076 case GTK_JUSTIFY_CENTER:
2077 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2079 case GTK_JUSTIFY_RIGHT:
2080 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2087 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2089 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2090 G_CALLBACK (modest_msg_edit_window_color_button_change),
2092 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2093 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2094 G_CALLBACK (modest_msg_edit_window_color_button_change),
2097 if (priv->current_size_index != buffer_format->font_size) {
2101 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2102 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2106 priv->current_size_index = buffer_format->font_size;
2108 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2109 markup = g_strconcat ("<span font_family='Sans'>",
2110 size_text, "</span>", NULL);
2112 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2116 gtk_tree_path_free (path);
2119 if (priv->current_face_index != buffer_format->font) {
2123 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2124 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2128 priv->current_face_index = buffer_format->font;
2129 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2130 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2131 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2138 g_free (buffer_format);
2142 #ifdef MODEST_HILDON_VERSION_0
2144 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2147 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2148 ModestMsgEditWindowPrivate *priv;
2149 GtkWidget *dialog = NULL;
2151 GdkColor *new_color = NULL;
2153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2154 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2156 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2157 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2158 g_free (buffer_format);
2160 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2161 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2162 if (new_color != NULL) {
2163 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2164 (gpointer) new_color);
2167 gtk_widget_destroy (dialog);
2172 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2175 ModestMsgEditWindowPrivate *priv;
2176 GtkWidget *dialog = NULL;
2178 GdkColor *old_color = NULL;
2179 const GdkColor *new_color = NULL;
2181 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2182 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2184 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2185 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2187 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2188 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2189 if (new_color != NULL)
2190 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2192 gtk_widget_destroy (dialog);
2198 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2201 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2202 ModestMsgEditWindowPrivate *priv;
2203 GtkWidget *dialog = NULL;
2205 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2206 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2208 dialog = hildon_color_chooser_new ();
2209 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2210 g_free (buffer_format);
2212 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2214 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2215 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2218 gtk_widget_destroy (dialog);
2223 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2226 ModestMsgEditWindowPrivate *priv;
2227 GtkWidget *dialog = NULL;
2228 GdkColor *old_color = NULL;
2230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2231 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2233 dialog = hildon_color_chooser_new ();
2234 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2236 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2238 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2239 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2241 gtk_widget_destroy (dialog);
2244 #endif /*!MODEST_HILDON_VERSION_0*/
2249 create_stream_for_uri (const gchar* uri)
2254 TnyStream *result = NULL;
2256 GnomeVFSHandle *handle = NULL;
2257 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2258 if (test == GNOME_VFS_OK) {
2259 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2260 /* Streams over OBEX (Bluetooth) are not seekable but
2261 * we expect them to be (we might need to read them
2262 * several times). So if this is a Bluetooth URI just
2263 * read the whole file into memory (this is not a fast
2264 * protocol so we can assume that these files are not
2265 * going to be very big) */
2266 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2267 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2268 TnyStream *memstream = tny_camel_mem_stream_new ();
2269 tny_stream_write_to_stream (vfssstream, memstream);
2270 g_object_unref (vfssstream);
2273 result = vfssstream;
2281 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2284 ModestMsgEditWindowPrivate *priv;
2285 GtkWidget *dialog = NULL;
2287 GSList *uris = NULL;
2288 GSList *uri_node = NULL;
2290 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2292 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2293 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2294 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2296 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2298 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2299 GTK_WINDOW (dialog), GTK_WINDOW (window));
2301 response = gtk_dialog_run (GTK_DIALOG (dialog));
2303 case GTK_RESPONSE_OK:
2305 gchar *current_folder;
2306 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2307 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2308 if (current_folder && current_folder != '\0') {
2310 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2311 current_folder, &err);
2313 g_debug ("Error storing latest used folder: %s", err->message);
2317 g_free (current_folder);
2323 gtk_widget_destroy (dialog);
2325 g_object_ref (window);
2326 /* The operation could take some time so allow the dialog to be closed */
2327 while (gtk_events_pending ())
2328 gtk_main_iteration ();
2330 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2332 GnomeVFSHandle *handle = NULL;
2333 GnomeVFSResult result;
2334 GtkTextIter position;
2335 GtkTextMark *insert_mark;
2337 uri = (const gchar *) uri_node->data;
2338 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2339 if (result == GNOME_VFS_OK) {
2341 GnomeVFSFileInfo *info;
2342 gchar *filename, *basename, *escaped_filename;
2343 TnyMimePart *mime_part;
2345 const gchar *mime_type = NULL;
2346 GnomeVFSURI *vfs_uri;
2347 guint64 stream_size;
2349 gnome_vfs_close (handle);
2350 vfs_uri = gnome_vfs_uri_new (uri);
2352 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2353 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2354 g_free (escaped_filename);
2355 gnome_vfs_uri_unref (vfs_uri);
2356 info = gnome_vfs_file_info_new ();
2358 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2359 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2361 mime_type = gnome_vfs_file_info_get_mime_type (info);
2363 mime_part = tny_platform_factory_new_mime_part
2364 (modest_runtime_get_platform_factory ());
2366 TnyStream *stream = create_stream_for_uri (uri);
2368 if (stream == NULL) {
2370 modest_platform_information_banner (NULL, NULL,
2371 _FM("sfil_ib_opening_not_allowed"));
2373 g_object_unref (mime_part);
2374 gnome_vfs_file_info_unref (info);
2378 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2380 content_id = g_strdup_printf ("%d", priv->next_cid);
2381 tny_mime_part_set_content_id (mime_part, content_id);
2382 g_free (content_id);
2385 basename = g_path_get_basename (filename);
2386 tny_mime_part_set_filename (mime_part, basename);
2389 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2391 if (pixbuf != NULL) {
2392 priv->images_size += stream_size;
2393 priv->images_count ++;
2394 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2395 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2396 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2397 tny_mime_part_get_content_id (mime_part), pixbuf);
2398 g_object_unref (pixbuf);
2400 tny_list_prepend (priv->images, (GObject *) mime_part);
2401 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2403 modest_platform_information_banner (NULL, NULL,
2404 _("mail_ib_file_operation_failed"));
2408 g_object_unref (mime_part);
2409 gnome_vfs_file_info_unref (info);
2413 g_object_unref (window);
2417 on_attach_file_response (GtkDialog *dialog,
2421 GSList *uris = NULL;
2423 GnomeVFSFileSize total_size, allowed_size;
2424 ModestMsgEditWindow *window;
2425 ModestMsgEditWindowPrivate *priv;
2430 case GTK_RESPONSE_OK:
2432 gchar *current_folder;
2434 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2435 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2436 if (current_folder && current_folder != '\0') {
2438 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2439 current_folder, &err);
2441 g_debug ("Error storing latest used folder: %s", err->message);
2445 g_free (current_folder);
2452 window = MODEST_MSG_EDIT_WINDOW (user_data);
2453 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2455 /* allowed size is the maximum size - what's already there */
2456 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2457 &att_num, &att_size);
2458 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2461 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2463 const gchar *uri = (const gchar *) uri_node->data;
2466 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2468 if (total_size > allowed_size) {
2469 g_warning ("%s: total size: %u",
2470 __FUNCTION__, (unsigned int)total_size);
2473 allowed_size -= total_size;
2475 g_slist_foreach (uris, (GFunc) g_free, NULL);
2476 g_slist_free (uris);
2478 gtk_widget_destroy (GTK_WIDGET (dialog));
2482 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2484 GtkWidget *dialog = NULL;
2485 ModestMsgEditWindowPrivate *priv;
2488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2492 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2495 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2496 GTK_FILE_CHOOSER_ACTION_OPEN);
2497 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2498 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2499 if (conf_folder && conf_folder[0] != '\0') {
2500 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2503 /* Set the default folder to images folder */
2504 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2505 ".documents", NULL);
2506 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2507 g_free (docs_folder);
2509 g_free (conf_folder);
2510 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2511 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2512 GTK_WINDOW (dialog), GTK_WINDOW (window));
2514 /* Connect to response & show */
2515 g_signal_connect (dialog, "response",
2516 G_CALLBACK (on_attach_file_response), window);
2517 gtk_widget_show (dialog);
2522 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2524 GnomeVFSFileSize allowed_size)
2527 GnomeVFSHandle *handle = NULL;
2528 ModestMsgEditWindowPrivate *priv;
2529 GnomeVFSResult result;
2530 GnomeVFSFileSize size = 0;
2531 g_return_val_if_fail (window, 0);
2532 g_return_val_if_fail (uri, 0);
2534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2536 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2537 if (result == GNOME_VFS_OK) {
2538 TnyMimePart *mime_part;
2540 const gchar *mime_type = NULL;
2542 gchar *escaped_filename;
2545 GnomeVFSFileInfo *info;
2546 GnomeVFSURI *vfs_uri;
2548 gnome_vfs_close (handle);
2549 vfs_uri = gnome_vfs_uri_new (uri);
2552 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2553 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2554 g_free (escaped_filename);
2555 gnome_vfs_uri_unref (vfs_uri);
2557 info = gnome_vfs_file_info_new ();
2559 if (gnome_vfs_get_file_info (uri,
2561 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2563 mime_type = gnome_vfs_file_info_get_mime_type (info);
2564 mime_part = tny_platform_factory_new_mime_part
2565 (modest_runtime_get_platform_factory ());
2567 /* try to get the attachment's size; this may fail for weird
2568 * file systems, like obex, upnp... */
2569 if (allowed_size != 0 &&
2570 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2572 if (size > allowed_size) {
2573 modest_platform_information_banner (NULL, NULL,
2574 _FM("sfil_ib_opening_not_allowed"));
2579 g_warning ("%s: could not get attachment size", __FUNCTION__);
2581 stream = create_stream_for_uri (uri);
2583 if (stream == NULL) {
2585 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2587 g_object_unref (mime_part);
2589 gnome_vfs_file_info_unref (info);
2593 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2594 g_object_unref (stream);
2596 content_id = g_strdup_printf ("%d", priv->next_cid);
2597 tny_mime_part_set_content_id (mime_part, content_id);
2598 g_free (content_id);
2601 basename = g_path_get_basename (filename);
2602 tny_mime_part_set_filename (mime_part, basename);
2605 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2606 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2608 info->size == 0, info->size);
2609 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2610 gtk_widget_show_all (priv->attachments_caption);
2611 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2613 g_object_unref (mime_part);
2614 gnome_vfs_file_info_unref (info);
2621 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2624 ModestMsgEditWindowPrivate *priv;
2627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 if (att_list == NULL) {
2631 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2632 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2633 g_object_unref (att_list);
2638 g_object_ref (att_list);
2641 if (tny_list_get_length (att_list) == 0) {
2642 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2644 gboolean dialog_response;
2645 gchar *message = NULL;
2646 gchar *filename = NULL;
2648 if (tny_list_get_length (att_list) == 1) {
2650 iter = tny_list_create_iterator (att_list);
2651 part = (TnyMimePart *) tny_iterator_get_current (iter);
2652 g_object_unref (iter);
2653 if (TNY_IS_MSG (part)) {
2654 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2656 filename = tny_header_dup_subject (header);
2657 g_object_unref (header);
2659 if (filename == NULL) {
2660 filename = g_strdup (_("mail_va_no_subject"));
2663 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2665 g_object_unref (part);
2667 filename = g_strdup ("");
2669 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2670 "emev_nc_delete_attachments",
2671 tny_list_get_length (att_list)), filename);
2674 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2678 if (dialog_response != GTK_RESPONSE_OK) {
2679 g_object_unref (att_list);
2683 for (iter = tny_list_create_iterator (att_list);
2684 !tny_iterator_is_done (iter);
2685 tny_iterator_next (iter)) {
2686 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2687 const gchar *att_id;
2688 tny_list_remove (priv->attachments, (GObject *) mime_part);
2690 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2692 if (tny_list_get_length (priv->attachments) == 0)
2693 gtk_widget_hide (priv->attachments_caption);
2694 att_id = tny_mime_part_get_content_id (mime_part);
2696 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2698 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2699 g_object_unref (mime_part);
2701 g_object_unref (iter);
2704 g_object_unref (att_list);
2706 /* if the last attachment has been removed, focus the Subject: field */
2707 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2708 gtk_widget_grab_focus (priv->subject_field);
2712 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2715 ModestMsgEditWindowPrivate *priv;
2716 GdkColor *new_color;
2717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2719 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2720 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2723 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2725 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2727 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2729 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2734 font_size_clicked (GtkToolButton *button,
2735 ModestMsgEditWindow *window)
2737 ModestMsgEditWindowPrivate *priv;
2738 GtkWidget *selector, *dialog;
2740 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2742 selector = hildon_touch_selector_new ();
2743 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2744 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2746 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2747 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2748 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2750 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2754 WPTextBufferFormat format;
2756 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2758 memset (&format, 0, sizeof (format));
2759 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2761 format.cs.font_size = TRUE;
2762 format.cs.text_position = TRUE;
2763 format.cs.font = TRUE;
2764 format.font_size = new_index;
2765 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2767 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2768 GINT_TO_POINTER (new_index)))
2769 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2771 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2772 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2773 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2774 size_text, "</span>", NULL);
2776 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2780 gtk_widget_destroy (dialog);
2782 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2787 font_face_clicked (GtkToolButton *button,
2788 ModestMsgEditWindow *window)
2790 ModestMsgEditWindowPrivate *priv;
2791 GtkWidget *selector, *dialog;
2792 GtkCellRenderer *renderer;
2794 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2796 selector = hildon_touch_selector_new ();
2797 renderer = gtk_cell_renderer_text_new ();
2798 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2799 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2800 renderer, "family", 0, "text", 0, NULL);
2801 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2803 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2804 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2805 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2807 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2808 gint new_font_index;
2812 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2813 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2814 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2818 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2820 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2821 GINT_TO_POINTER(new_font_index)))
2822 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2824 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2825 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2827 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2831 gtk_tree_path_free (path);
2834 gtk_widget_destroy (dialog);
2836 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2841 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2844 ModestMsgEditWindowPrivate *priv = NULL;
2845 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2847 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2848 if (!priv->update_caption_visibility)
2851 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2853 gtk_widget_show (priv->cc_caption);
2855 gtk_widget_hide (priv->cc_caption);
2857 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2861 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2864 ModestMsgEditWindowPrivate *priv = NULL;
2865 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2868 if (!priv->update_caption_visibility)
2871 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2873 gtk_widget_show (priv->bcc_caption);
2875 gtk_widget_hide (priv->bcc_caption);
2877 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2881 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2882 ModestRecptEditor *editor)
2884 ModestMsgEditWindowPrivate *priv;
2886 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2887 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2889 /* we check for low-mem; in that case, show a warning, and don't allow
2890 * for the addressbook
2892 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2895 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2897 if (editor == NULL) {
2898 GtkWidget *view_focus;
2899 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2901 /* This code should be kept in sync with ModestRecptEditor. The
2902 textview inside the recpt editor is the one that really gets the
2903 focus. As it's inside a scrolled window, and this one inside the
2904 hbox recpt editor inherits from, we'll need to go up in the
2905 hierarchy to know if the text view is part of the recpt editor
2906 or if it's a different text entry */
2908 if (gtk_widget_get_parent (view_focus)) {
2909 GtkWidget *first_parent;
2911 first_parent = gtk_widget_get_parent (view_focus);
2912 if (gtk_widget_get_parent (first_parent) &&
2913 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2914 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2919 editor = MODEST_RECPT_EDITOR (priv->to_field);
2923 modest_address_book_select_addresses (editor);
2928 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2930 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2932 modest_msg_edit_window_open_addressbook (window, NULL);
2936 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2937 gboolean show_toolbar)
2939 ModestWindowPrivate *parent_priv;
2940 ModestMsgEditWindowPrivate *priv;
2942 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2944 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2946 /* We can not just use the code of
2947 modest_msg_edit_window_setup_toolbar because it has a
2948 mixture of both initialization and creation code. */
2950 gint current_format;
2951 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2952 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2953 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2954 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2956 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2959 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2964 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2965 TnyHeaderFlags priority_flags)
2967 ModestMsgEditWindowPrivate *priv;
2968 ModestWindowPrivate *parent_priv;
2970 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2972 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2973 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2975 if (priv->priority_flags != priority_flags) {
2976 GtkAction *priority_action = NULL;
2978 priv->priority_flags = priority_flags;
2980 switch (priority_flags) {
2981 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2982 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2983 MODEST_HEADER_ICON_HIGH,
2984 HILDON_ICON_SIZE_SMALL);
2985 gtk_widget_show (priv->priority_icon);
2986 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2987 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2989 case TNY_HEADER_FLAG_LOW_PRIORITY:
2990 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2991 MODEST_HEADER_ICON_LOW,
2992 HILDON_ICON_SIZE_SMALL);
2993 gtk_widget_show (priv->priority_icon);
2994 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2995 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2998 gtk_widget_hide (priv->priority_icon);
2999 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3000 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3003 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3004 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3006 gtk_widget_queue_resize (priv->subject_box);
3010 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3013 ModestMsgEditWindowPrivate *priv;
3014 ModestWindowPrivate *parent_priv;
3015 gint current_format;
3017 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3019 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3023 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3025 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3027 if (parent_priv->toolbar) {
3028 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3029 gtk_widget_hide (parent_priv->toolbar);
3031 gtk_widget_show (parent_priv->toolbar);
3035 if (current_format != file_format) {
3036 switch (file_format) {
3037 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3038 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3039 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3041 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3045 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3046 response = gtk_dialog_run (GTK_DIALOG (dialog));
3047 gtk_widget_destroy (dialog);
3048 if (response == GTK_RESPONSE_OK) {
3049 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3050 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3052 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3053 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3058 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3059 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3060 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3065 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3068 ModestMsgEditWindowPrivate *priv;
3069 WPTextBufferFormat oldfmt, fmt;
3070 gint old_position = 0;
3074 GdkColor *color = NULL;
3075 gboolean bold, bold_set, italic, italic_set;
3076 gboolean underline, underline_set;
3077 gboolean strikethrough, strikethrough_set;
3078 gboolean position_set;
3079 gboolean font_size_set, font_set, color_set;
3082 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3085 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3086 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3087 GTK_WINDOW(dialog), GTK_WINDOW (window));
3089 /* First we get the currently selected font information */
3090 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3092 switch (oldfmt.text_position) {
3093 case TEXT_POSITION_NORMAL:
3096 case TEXT_POSITION_SUPERSCRIPT:
3104 g_object_set (G_OBJECT (dialog),
3105 "bold", oldfmt.bold != FALSE,
3106 "bold-set", !oldfmt.cs.bold,
3107 "underline", oldfmt.underline != FALSE,
3108 "underline-set", !oldfmt.cs.underline,
3109 "italic", oldfmt.italic != FALSE,
3110 "italic-set", !oldfmt.cs.italic,
3111 "strikethrough", oldfmt.strikethrough != FALSE,
3112 "strikethrough-set", !oldfmt.cs.strikethrough,
3113 "color", &oldfmt.color,
3114 "color-set", !oldfmt.cs.color,
3115 "size", wp_font_size[oldfmt.font_size],
3116 "size-set", !oldfmt.cs.font_size,
3117 "position", old_position,
3118 "position-set", !oldfmt.cs.text_position,
3119 "family", wp_get_font_name (oldfmt.font),
3120 "family-set", !oldfmt.cs.font,
3123 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3124 GTK_WINDOW (dialog), GTK_WINDOW (window));
3125 gtk_widget_show_all (dialog);
3126 priv->font_dialog = dialog;
3127 response = gtk_dialog_run (GTK_DIALOG (dialog));
3128 priv->font_dialog = NULL;
3129 if (response == GTK_RESPONSE_OK) {
3131 g_object_get( dialog,
3133 "bold-set", &bold_set,
3134 "underline", &underline,
3135 "underline-set", &underline_set,
3137 "italic-set", &italic_set,
3138 "strikethrough", &strikethrough,
3139 "strikethrough-set", &strikethrough_set,
3141 "color-set", &color_set,
3143 "size-set", &font_size_set,
3144 "family", &font_name,
3145 "family-set", &font_set,
3146 "position", &position,
3147 "position-set", &position_set,
3152 if (response == GTK_RESPONSE_OK) {
3153 memset(&fmt, 0, sizeof(fmt));
3159 fmt.italic = italic;
3160 fmt.cs.italic = TRUE;
3162 if (underline_set) {
3163 fmt.underline = underline;
3164 fmt.cs.underline = TRUE;
3166 if (strikethrough_set) {
3167 fmt.strikethrough = strikethrough;
3168 fmt.cs.strikethrough = TRUE;
3173 ? TEXT_POSITION_NORMAL
3174 : ( ( position == 1 )
3175 ? TEXT_POSITION_SUPERSCRIPT
3176 : TEXT_POSITION_SUBSCRIPT );
3177 fmt.cs.text_position = TRUE;
3178 fmt.font_size = oldfmt.font_size;
3182 fmt.cs.color = TRUE;
3185 fmt.font = wp_get_font_index(font_name,
3190 if (font_size_set) {
3191 fmt.cs.font_size = TRUE;
3192 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3194 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3195 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3197 gtk_widget_destroy (dialog);
3199 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3203 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3205 ModestMsgEditWindowPrivate *priv;
3207 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3208 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3210 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3212 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3213 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3217 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3219 ModestMsgEditWindowPrivate *priv;
3221 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3222 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3224 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3226 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3227 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3232 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3234 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3236 priv->can_undo = can_undo;
3240 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3242 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3244 priv->can_redo = can_redo;
3248 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3250 ModestMsgEditWindowPrivate *priv;
3251 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3252 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3254 return priv->can_undo;
3258 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3260 ModestMsgEditWindowPrivate *priv;
3261 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 return priv->can_redo;
3269 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3272 GtkTextIter match_start, match_end;
3274 if (image_id == NULL)
3277 gtk_text_buffer_get_start_iter (buffer, &iter);
3279 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3280 GSList *tags = gtk_text_iter_get_tags (&match_start);
3282 for (node = tags; node != NULL; node = g_slist_next (node)) {
3283 GtkTextTag *tag = (GtkTextTag *) node->data;
3284 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3285 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3286 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3288 offset = gtk_text_iter_get_offset (&match_start);
3289 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3290 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3294 gtk_text_iter_forward_char (&iter);
3299 message_is_empty (ModestMsgEditWindow *window)
3301 ModestMsgEditWindowPrivate *priv = NULL;
3303 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3304 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3306 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3307 * so we can ignore markup.
3309 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3312 count = gtk_text_buffer_get_char_count (buf);
3318 msg_body_focus (GtkWidget *focus,
3319 GdkEventFocus *event,
3323 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3324 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3325 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3330 recpt_field_changed (GtkTextBuffer *buffer,
3331 ModestMsgEditWindow *editor)
3333 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3334 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3338 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3340 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3341 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3345 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3348 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3349 GtkTextBuffer *buffer;
3351 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3352 gtk_text_buffer_set_modified (buffer, modified);
3353 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3354 gtk_text_buffer_set_modified (buffer, modified);
3355 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3356 gtk_text_buffer_set_modified (buffer, modified);
3357 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3361 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3363 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3364 const char *account_name;
3365 GtkTextBuffer *buffer;
3367 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3368 if (gtk_text_buffer_get_modified (buffer))
3370 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3371 if (gtk_text_buffer_get_modified (buffer))
3373 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3374 if (gtk_text_buffer_get_modified (buffer))
3376 if (gtk_text_buffer_get_modified (priv->text_buffer))
3379 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3380 if (priv->original_mailbox) {
3381 if (!account_name || strcmp (account_name, priv->original_mailbox))
3383 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3394 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3396 ModestMsgEditWindowPrivate *priv = NULL;
3398 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3399 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3401 /* check if there's no recipient added */
3402 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3403 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3404 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3405 /* no recipient contents, then select contacts */
3406 modest_msg_edit_window_open_addressbook (window, NULL);
3410 g_object_ref (window);
3411 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3412 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3413 g_object_unref (window);
3416 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3417 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3418 g_object_unref (window);
3421 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3422 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3423 g_object_unref (window);
3427 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3428 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3429 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3430 g_object_unref (window);
3437 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3438 ModestMsgEditWindow *window)
3440 modest_msg_edit_window_offer_attach_file (window);
3444 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3446 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3448 return priv->clipboard_text;
3452 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3454 ModestMsgEditWindow *window)
3456 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3457 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3460 /* It could happen that the window was already closed */
3461 if (!GTK_WIDGET_VISIBLE (window))
3464 g_object_ref (window);
3465 text = gtk_clipboard_wait_for_text (selection_clipboard);
3467 if (priv->clipboard_text != NULL) {
3468 g_free (priv->clipboard_text);
3470 priv->clipboard_text = text;
3472 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3474 g_object_unref (window);
3477 static gboolean clipboard_owner_change_idle (gpointer userdata)
3479 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3480 ModestMsgEditWindowPrivate *priv;
3482 gdk_threads_enter ();
3483 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3486 priv->clipboard_owner_idle = 0;
3487 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3488 gdk_threads_leave ();
3494 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3496 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3497 if (priv->clipboard_owner_idle == 0) {
3498 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3499 clipboard_owner_change_idle,
3500 g_object_ref (window),
3506 subject_field_move_cursor (GtkEntry *entry,
3507 GtkMovementStep step,
3512 /* It could happen that the window was already closed */
3513 if (!GTK_WIDGET_VISIBLE (window))
3516 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3520 update_window_title (ModestMsgEditWindow *window)
3522 ModestMsgEditWindowPrivate *priv = NULL;
3523 const gchar *subject;
3525 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3526 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3527 if (subject == NULL || subject[0] == '\0')
3528 subject = _("mail_va_new_email");
3530 gtk_window_set_title (GTK_WINDOW (window), subject);
3536 body_insert_text (GtkTextBuffer *buffer,
3537 GtkTextIter *location,
3540 ModestMsgEditWindow *window)
3542 GtkTextIter end_iter;
3545 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3547 offset = gtk_text_iter_get_offset (&end_iter);
3549 if (offset + len > MAX_BODY_LENGTH) {
3550 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3551 if (offset < MAX_BODY_LENGTH)
3555 /* Prevent endless recursion */
3556 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3557 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3558 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3559 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3561 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3565 if (offset + len > MAX_BODY_LENGTH) {
3566 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3567 _CS("ckdg_ib_maximum_characters_reached"));
3572 subject_field_changed (GtkEditable *editable,
3573 ModestMsgEditWindow *window)
3575 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3576 update_window_title (window);
3577 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3578 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3579 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3582 subject_field_insert_text (GtkEditable *editable,
3584 gint new_text_length,
3586 ModestMsgEditWindow *window)
3588 GString *result = g_string_new ("");
3590 gint result_len = 0;
3591 const gchar *entry_text = NULL;
3594 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3595 old_length = g_utf8_strlen (entry_text, -1);
3597 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3598 gunichar c = g_utf8_get_char_validated (current, 8);
3599 /* Invalid unichar, stop */
3605 result = g_string_append_unichar (result, c);
3609 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3610 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3613 /* Prevent endless recursion */
3614 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3615 g_signal_emit_by_name (editable, "insert-text",
3616 (gpointer) result->str, (gpointer) result->len,
3617 (gpointer) position, (gpointer) window);
3618 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3622 if (result_len + old_length > 1000) {
3623 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3624 _CS("ckdg_ib_maximum_characters_reached"));
3626 g_string_free (result, TRUE);
3630 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3633 ModestMsgEditWindowPrivate *priv = NULL;
3635 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3638 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3641 gtk_widget_show_all (priv->find_toolbar);
3642 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3644 gtk_widget_hide_all (priv->find_toolbar);
3645 gtk_widget_grab_focus (priv->msg_body);
3650 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3652 GtkTextIter *match_start,
3653 GtkTextIter *match_end)
3655 GtkTextIter end_iter;
3656 gchar *str_casefold;
3659 gchar *range_casefold;
3662 gboolean result = FALSE;
3669 gtk_text_iter_forward_to_end (&end_iter);
3671 str_casefold = g_utf8_casefold (str, -1);
3672 str_chars_n = strlen (str);
3674 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3675 range_casefold = g_utf8_casefold (range_text, -1);
3676 range_chars_n = strlen (range_casefold);
3678 if (range_chars_n < str_chars_n) {
3679 g_free (str_casefold);
3680 g_free (range_text);
3681 g_free (range_casefold);
3685 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3686 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3687 if (!g_utf8_collate (range_subtext, str_casefold)) {
3688 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3690 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3691 match_start, match_end, NULL)) {
3692 g_warning ("Matched string with collate, but not matched in model");
3694 g_free (found_text);
3696 g_free (range_subtext);
3700 g_free (str_casefold);
3701 g_free (range_text);
3702 g_free (range_casefold);
3709 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3710 ModestMsgEditWindow *window)
3712 gchar *current_search = NULL;
3713 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3715 GtkTextIter selection_start, selection_end;
3716 GtkTextIter match_start, match_end;
3717 gboolean continue_search = FALSE;
3719 if (message_is_empty (window)) {
3720 g_free (priv->last_search);
3721 priv->last_search = NULL;
3722 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3726 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3727 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3728 g_free (current_search);
3729 g_free (priv->last_search);
3730 priv->last_search = NULL;
3731 /* Information banner about empty search */
3732 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3736 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3737 continue_search = TRUE;
3739 g_free (priv->last_search);
3740 priv->last_search = g_strdup (current_search);
3743 if (continue_search) {
3744 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3745 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3746 &match_start, &match_end);
3748 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3750 GtkTextIter buffer_start;
3751 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3752 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3753 &match_start, &match_end);
3755 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3758 /* Mark as selected the string found in search */
3760 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3761 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3762 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3764 g_free (priv->last_search);
3765 priv->last_search = NULL;
3767 g_free (current_search);
3771 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3773 ModestMsgEditWindowPrivate *priv;
3775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3780 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3783 ModestMsgEditWindowPrivate *priv;
3785 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3790 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3791 ModestMsgEditWindow *window)
3793 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3797 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3800 ModestMsgEditWindowPrivate *priv;
3801 TnyHeader *header = NULL;
3803 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3804 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3806 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3808 if (priv->draft_msg != NULL) {
3809 g_object_unref (priv->draft_msg);
3812 if (draft != NULL) {
3813 g_object_ref (draft);
3814 header = tny_msg_get_header (draft);
3815 if (priv->msg_uid) {
3816 g_free (priv->msg_uid);
3817 priv->msg_uid = NULL;
3819 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3822 priv->draft_msg = draft;
3826 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3827 GtkTextIter *start, GtkTextIter *end,
3830 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3831 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3834 if (tag == NULL) return;
3835 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3836 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3837 replace_with_images (window, priv->images);
3842 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3845 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3847 g_return_if_fail (TNY_IS_MIME_PART (part));
3848 tny_list_prepend (priv->attachments, (GObject *) part);
3849 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3850 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3851 gtk_widget_show_all (priv->attachments_caption);
3852 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3856 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3858 ModestMsgEditWindowPrivate *priv;
3860 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3863 return priv->msg_uid;
3867 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3868 ModestMsgEditWindowWidgetType widget_type)
3870 ModestMsgEditWindowPrivate *priv;
3872 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3873 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3875 switch (widget_type) {
3876 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3877 return priv->msg_body;
3879 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3880 return priv->to_field;
3882 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3883 return priv->cc_field;
3885 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3886 return priv->bcc_field;
3888 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3889 return priv->subject_field;
3891 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3892 return priv->attachments_view;
3900 remove_tags (WPTextBuffer *buffer)
3902 GtkTextIter start, end;
3904 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3905 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3907 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3911 on_account_removed (TnyAccountStore *account_store,
3912 TnyAccount *account,
3915 /* Do nothing if it's a store account, because we use the
3916 transport to send the messages */
3917 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3918 const gchar *parent_acc = NULL;
3919 const gchar *our_acc = NULL;
3921 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3922 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3923 /* Close this window if I'm showing a message of the removed account */
3924 if (strcmp (parent_acc, our_acc) == 0)
3925 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3929 static void update_signature (ModestMsgEditWindow *self,
3930 const gchar *old_account,
3931 const gchar *new_account)
3933 ModestMsgEditWindowPrivate *priv;
3934 gboolean has_old_signature, has_new_signature;
3936 GtkTextIter match_start, match_end;
3937 ModestAccountMgr *mgr;
3939 gchar *full_signature;
3941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3943 gtk_text_buffer_begin_user_action (priv->text_buffer);
3945 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3946 mgr = modest_runtime_get_account_mgr ();
3950 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3951 if (has_old_signature) {
3952 full_signature = g_strconcat ("\n--\n", signature, NULL);
3953 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3954 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3956 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3957 &match_start, &match_end, NULL)) {
3960 g_free (full_signature);
3965 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3966 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3967 if (has_new_signature) {
3968 full_signature = g_strconcat ("\n--\n", signature, NULL);
3969 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3970 g_free (full_signature);
3973 gtk_text_buffer_end_user_action (priv->text_buffer);
3977 from_field_changed (HildonPickerButton *button,
3978 ModestMsgEditWindow *self)
3980 ModestMsgEditWindowPrivate *priv;
3981 gchar *old_account, *new_account;
3983 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3985 old_account = priv->last_from_account;
3986 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3987 new_account = priv->last_from_account;
3989 update_signature (self, old_account, new_account);
3993 typedef struct _MessageSettingsHelper {
3994 ModestMsgEditWindow *window;
3995 GSList *priority_group;
3996 GSList *format_group;
3997 GtkToggleButton *current_priority;
3998 GtkToggleButton *current_format;
3999 } MessageSettingsHelper;
4002 on_priority_toggle (GtkToggleButton *button,
4003 MessageSettingsHelper *helper)
4006 ModestMsgEditWindowPrivate *priv;
4008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4009 if (gtk_toggle_button_get_active (button)) {
4011 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4012 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4013 if ((node_button != button) &&
4014 gtk_toggle_button_get_active (node_button)) {
4015 gtk_toggle_button_set_active (node_button, FALSE);
4018 helper->current_priority = button;
4020 gboolean found = FALSE;
4021 /* If no one is active, activate it again */
4022 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4023 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4024 if (gtk_toggle_button_get_active (node_button)) {
4030 gtk_toggle_button_set_active (button, TRUE);
4036 on_format_toggle (GtkToggleButton *button,
4037 MessageSettingsHelper *helper)
4040 ModestMsgEditWindowPrivate *priv;
4042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4043 if (gtk_toggle_button_get_active (button)) {
4045 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4046 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4047 if ((node_button != button) &&
4048 gtk_toggle_button_get_active (node_button)) {
4049 gtk_toggle_button_set_active (node_button, FALSE);
4052 helper->current_format = button;
4054 gboolean found = FALSE;
4055 /* If no one is active, activate it again */
4056 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4057 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4058 if (gtk_toggle_button_get_active (node_button)) {
4064 gtk_toggle_button_set_active (button, TRUE);
4071 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4076 GtkWidget *priority_hbox;
4077 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4078 GtkWidget *captioned;
4079 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4080 GtkWidget *format_hbox;
4081 GtkWidget *html_toggle, *text_toggle;
4082 ModestMsgEditWindowPrivate *priv;
4083 MessageSettingsHelper helper = {0,};
4085 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4087 helper.window = window;
4088 helper.priority_group = NULL;
4089 helper.format_group = NULL;
4091 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4092 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4094 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4095 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4096 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4097 vbox = gtk_vbox_new (FALSE, 0);
4098 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4099 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4100 gtk_container_add (GTK_CONTAINER (align), vbox);
4101 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4102 gtk_widget_show (align);
4103 gtk_widget_show (vbox);
4105 /* Priority toggles */
4106 priority_hbox = gtk_hbox_new (TRUE, 0);
4107 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4108 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4109 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4110 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4111 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4112 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4113 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4114 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4115 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4116 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4117 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4118 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4119 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4120 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4121 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4122 gtk_widget_show_all (priority_hbox);
4123 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4124 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4125 gtk_widget_show (captioned);
4126 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4128 /* format toggles */
4129 format_hbox = gtk_hbox_new (TRUE, 0);
4130 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4131 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4132 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4133 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4134 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4135 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4136 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4137 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4138 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4139 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4140 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4141 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4142 gtk_widget_show_all (format_hbox);
4143 gtk_widget_show (format_hbox);
4144 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4147 g_object_unref (title_sizegroup);
4148 g_object_unref (value_sizegroup);
4150 /* Set current values */
4151 switch (priv->priority_flags) {
4152 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4153 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4154 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4156 case TNY_HEADER_FLAG_LOW_PRIORITY:
4157 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4158 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4161 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4162 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4166 switch (modest_msg_edit_window_get_format (window)) {
4167 case MODEST_MSG_EDIT_FORMAT_TEXT:
4168 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4169 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4171 case MODEST_MSG_EDIT_FORMAT_HTML:
4173 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4174 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4178 /* Signal connects */
4179 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4180 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4181 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4182 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4183 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4185 /* Save settings if the user clicked on done */
4186 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4187 TnyHeaderFlags flags;
4188 ModestMsgEditFormat old_format, new_format;
4190 /* Set priority flags */
4191 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4192 if (priv->priority_flags != flags)
4193 modest_msg_edit_window_set_priority_flags (window, flags);
4195 /* Set edit format */
4196 old_format = modest_msg_edit_window_get_format (window);
4197 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4198 if (old_format != new_format) {
4199 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4200 modest_msg_edit_window_set_file_format (window, file_format);
4204 gtk_widget_destroy (dialog);
4205 g_slist_free (helper.priority_group);
4209 on_message_settings (GtkAction *action,
4210 ModestMsgEditWindow *window)
4212 modest_msg_edit_window_show_msg_settings_dialog (window);
4216 on_cc_button_toggled (HildonCheckButton *button,
4217 ModestMsgEditWindow *window)
4219 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4221 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4222 hildon_check_button_get_active (button));
4226 on_bcc_button_toggled (HildonCheckButton *button,
4227 ModestMsgEditWindow *window)
4229 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4231 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4232 hildon_check_button_get_active (button));
4236 setup_menu (ModestMsgEditWindow *self)
4238 ModestMsgEditWindowPrivate *priv = NULL;
4240 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4244 /* Settings menu buttons */
4245 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4246 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4248 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4249 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4250 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4252 priv->cc_button = hildon_check_button_new (0);
4253 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4254 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4256 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4258 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4259 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4260 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4261 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4263 priv->bcc_button = hildon_check_button_new (0);
4264 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4265 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4267 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4269 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4270 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4271 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4272 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4274 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4275 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4276 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4277 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: add attachment"), NULL,
4278 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4280 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4281 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4282 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4283 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4284 APP_MENU_CALLBACK (on_message_settings),
4286 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4287 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4292 emit_open_addressbook (GtkButton *button,
4293 ModestRecptEditor *editor)
4295 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4299 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4300 const gchar *label, GtkWidget *control)
4302 GtkWidget *abook_button;
4305 GtkWidget *label_widget;
4307 box = gtk_hbox_new (FALSE, 0);
4309 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4310 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4312 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4313 label_widget = gtk_label_new (label);
4314 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4315 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4317 gtk_container_add (GTK_CONTAINER (align), abook_button);
4318 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4319 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4320 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4321 if (title_size_group)
4322 gtk_size_group_add_widget (title_size_group, label_widget);
4323 if (value_size_group)
4324 gtk_size_group_add_widget (value_size_group, control);
4326 g_signal_connect (G_OBJECT (abook_button), "clicked",
4327 G_CALLBACK (emit_open_addressbook), control);