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/ToolbarSend");
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/ActionsBold");
1556 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1557 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1558 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1559 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1560 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1562 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1563 will not show the tool items added to the placeholders) */
1564 gtk_widget_show_all (parent_priv->toolbar);
1566 /* Set the no show all *after* showing all items. We do not
1567 want the toolbar to be shown with a show all because it
1568 could go agains the gconf setting regarding showing or not
1569 the toolbar of the editor window */
1570 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1576 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1579 ModestWindowPrivate *parent_priv;
1580 ModestMsgEditWindowPrivate *priv;
1581 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1582 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1583 ModestWindowMgr *mgr = NULL;
1585 g_return_val_if_fail (msg, NULL);
1586 g_return_val_if_fail (account_name, NULL);
1588 mgr = modest_runtime_get_window_mgr ();
1590 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1593 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1595 /* Menubar. Update the state of some toggles */
1596 priv->from_field_protos = get_transports ();
1597 priv->original_mailbox = NULL;
1598 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1599 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1600 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1601 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1602 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1603 priv->original_mailbox = g_strdup (mailbox);
1604 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1605 /* We set the first mailbox as the active mailbox */
1606 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1607 if (priv->original_mailbox != NULL)
1608 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1609 (gpointer) priv->original_mailbox);
1611 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1612 (gpointer) account_name);
1614 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1616 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1617 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1619 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1620 hildon_touch_selector_get_current_text
1621 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1622 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1623 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1626 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1628 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1630 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1631 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1633 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1635 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1636 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1637 /* Add common dimming rules */
1638 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1639 modest_msg_edit_window_toolbar_dimming_entries,
1640 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1641 MODEST_WINDOW (obj));
1642 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_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_size_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->font_face_toolitem,
1649 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1650 MODEST_WINDOW (obj));
1651 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1652 G_CALLBACK (modest_ui_dimming_rules_on_send),
1653 MODEST_WINDOW (obj));
1654 /* Insert dimming rules group for this window */
1655 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1656 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1658 /* Setup app menu */
1659 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1661 /* Checks the dimming rules */
1662 g_object_unref (toolbar_rules_group);
1663 g_object_unref (clipboard_rules_group);
1664 gtk_widget_hide (priv->priority_icon);
1665 gtk_widget_queue_resize (priv->subject_box);
1666 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1668 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1670 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1671 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1672 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1673 priv->update_caption_visibility = TRUE;
1675 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1677 /* Track account-removed signal, this window should be closed
1678 in the case we're creating a mail associated to the account
1680 priv->account_removed_handler_id =
1681 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1683 G_CALLBACK(on_account_removed),
1686 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1688 return (ModestWindow*) obj;
1692 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1694 GString **string_buffer = (GString **) user_data;
1696 *string_buffer = g_string_append (*string_buffer, buffer);
1702 * @result: A new string which should be freed with g_free().
1705 get_formatted_data (ModestMsgEditWindow *edit_window)
1707 ModestMsgEditWindowPrivate *priv;
1708 GString *string_buffer = g_string_new ("");
1710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1712 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1714 modest_text_utils_hyperlinkify (string_buffer);
1716 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1718 return g_string_free (string_buffer, FALSE);
1723 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1726 const gchar *account_name;
1727 ModestMsgEditWindowPrivate *priv;
1728 TnyIterator *att_iter;
1729 const gchar *picker_active_id;
1731 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1735 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1736 g_return_val_if_fail (picker_active_id, NULL);
1737 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1739 /* don't free these (except from) */
1740 data = g_slice_new0 (MsgData);
1741 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1742 data->account_name = g_strdup (account_name);
1743 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1744 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1745 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1746 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1747 data->references = g_strdup (priv->references);
1748 data->in_reply_to = g_strdup (priv->in_reply_to);
1749 if (priv->draft_msg) {
1750 data->draft_msg = g_object_ref (priv->draft_msg);
1751 } else if (priv->outbox_msg) {
1752 data->draft_msg = g_object_ref (priv->outbox_msg);
1754 data->draft_msg = NULL;
1757 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1759 gtk_text_buffer_get_bounds (buf, &b, &e);
1760 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1762 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1763 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1765 data->html_body = NULL;
1767 /* deep-copy the data */
1768 att_iter = tny_list_create_iterator (priv->attachments);
1769 data->attachments = NULL;
1770 while (!tny_iterator_is_done (att_iter)) {
1771 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1772 if (!(TNY_IS_MIME_PART(part))) {
1773 g_warning ("strange data in attachment list");
1774 g_object_unref (part);
1775 tny_iterator_next (att_iter);
1778 data->attachments = g_list_append (data->attachments,
1780 tny_iterator_next (att_iter);
1782 g_object_unref (att_iter);
1784 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1785 att_iter = tny_list_create_iterator (priv->images);
1786 data->images = NULL;
1787 while (!tny_iterator_is_done (att_iter)) {
1788 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1790 if (!(TNY_IS_MIME_PART(part))) {
1791 g_warning ("strange data in attachment list");
1792 g_object_unref (part);
1793 tny_iterator_next (att_iter);
1796 cid = tny_mime_part_get_content_id (part);
1798 gchar *image_tag_id;
1799 GtkTextTag *image_tag;
1801 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1802 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1803 g_free (image_tag_id);
1805 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1807 ((gtk_text_iter_has_tag (&iter, image_tag))||
1808 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1809 data->images = g_list_append (data->images,
1810 g_object_ref (part));
1812 g_object_unref (part);
1813 tny_iterator_next (att_iter);
1815 g_object_unref (att_iter);
1817 data->priority_flags = priv->priority_flags;
1824 unref_gobject (GObject *obj, gpointer data)
1826 if (!G_IS_OBJECT(obj))
1828 g_object_unref (obj);
1832 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1835 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1843 g_free (data->from);
1844 g_free (data->subject);
1845 g_free (data->plain_body);
1846 g_free (data->html_body);
1847 g_free (data->account_name);
1848 g_free (data->references);
1849 g_free (data->in_reply_to);
1851 if (data->draft_msg != NULL) {
1852 g_object_unref (data->draft_msg);
1853 data->draft_msg = NULL;
1856 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1857 g_list_free (data->attachments);
1858 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1859 g_list_free (data->images);
1861 g_slice_free (MsgData, data);
1865 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1867 guint64 *parts_size)
1869 ModestMsgEditWindowPrivate *priv;
1871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1873 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1875 /* TODO: add images */
1876 *parts_size += priv->images_size;
1877 *parts_count += priv->images_count;
1882 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1885 ModestMsgEditWindowPrivate *priv = NULL;
1886 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1888 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1890 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1892 return MODEST_MSG_EDIT_FORMAT_HTML;
1894 return MODEST_MSG_EDIT_FORMAT_TEXT;
1898 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1899 ModestMsgEditFormat format)
1901 ModestMsgEditWindowPrivate *priv;
1902 ModestWindowPrivate *parent_priv;
1904 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1906 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1909 case MODEST_MSG_EDIT_FORMAT_HTML:
1910 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1911 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1913 case MODEST_MSG_EDIT_FORMAT_TEXT:
1914 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1915 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1918 g_return_if_reached ();
1922 ModestMsgEditFormatState *
1923 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1925 ModestMsgEditFormatState *format_state = NULL;
1926 ModestMsgEditWindowPrivate *priv;
1927 WPTextBufferFormat *buffer_format;
1929 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1931 buffer_format = g_new0 (WPTextBufferFormat, 1);
1932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1934 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1936 format_state = g_new0 (ModestMsgEditFormatState, 1);
1937 format_state->bold = buffer_format->bold&0x1;
1938 format_state->italics = buffer_format->italic&0x1;
1939 format_state->bullet = buffer_format->bullet&0x1;
1940 format_state->color = buffer_format->color;
1941 format_state->font_size = buffer_format->font_size;
1942 format_state->font_family = wp_get_font_name (buffer_format->font);
1943 format_state->justification = buffer_format->justification;
1944 g_free (buffer_format);
1946 return format_state;
1951 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1952 const ModestMsgEditFormatState *format_state)
1954 ModestMsgEditWindowPrivate *priv;
1955 WPTextBufferFormat *buffer_format;
1956 WPTextBufferFormat *current_format;
1958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1959 g_return_if_fail (format_state != NULL);
1961 buffer_format = g_new0 (WPTextBufferFormat, 1);
1962 current_format = g_new0 (WPTextBufferFormat, 1);
1964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1965 gtk_widget_grab_focus (priv->msg_body);
1966 buffer_format->bold = (format_state->bold != FALSE);
1967 buffer_format->italic = (format_state->italics != FALSE);
1968 buffer_format->color = format_state->color;
1969 buffer_format->font_size = format_state->font_size;
1970 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1971 buffer_format->justification = format_state->justification;
1972 buffer_format->bullet = format_state->bullet;
1974 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1976 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1977 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1978 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1979 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1980 buffer_format->cs.font = (buffer_format->font != current_format->font);
1981 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1982 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1984 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1985 if (buffer_format->cs.bold) {
1986 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1987 GINT_TO_POINTER (buffer_format->bold&0x1));
1989 if (buffer_format->cs.italic) {
1990 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1991 GINT_TO_POINTER (buffer_format->italic&0x1));
1993 if (buffer_format->cs.color) {
1994 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1995 GINT_TO_POINTER (&(buffer_format->color)));
1997 if (buffer_format->cs.font_size) {
1998 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1999 GINT_TO_POINTER (buffer_format->font_size));
2001 if (buffer_format->cs.justification) {
2002 switch (buffer_format->justification) {
2003 case GTK_JUSTIFY_LEFT:
2004 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2005 GINT_TO_POINTER(TRUE));
2007 case GTK_JUSTIFY_CENTER:
2008 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2009 GINT_TO_POINTER(TRUE));
2011 case GTK_JUSTIFY_RIGHT:
2012 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2013 GINT_TO_POINTER(TRUE));
2020 if (buffer_format->cs.font) {
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2022 GINT_TO_POINTER (buffer_format->font));
2024 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2025 if (buffer_format->cs.bullet) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2027 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2029 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2031 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2033 g_free (buffer_format);
2034 g_free (current_format);
2036 /* Check dimming rules */
2037 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2038 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2042 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2044 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2046 ModestWindowPrivate *parent_priv;
2047 ModestMsgEditWindowPrivate *priv;
2049 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2052 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2053 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2054 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2055 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2057 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2058 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2059 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2062 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2064 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2065 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2067 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2068 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2070 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2071 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2074 switch (buffer_format->justification)
2076 case GTK_JUSTIFY_LEFT:
2077 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2079 case GTK_JUSTIFY_CENTER:
2080 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2082 case GTK_JUSTIFY_RIGHT:
2083 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2090 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2092 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2093 G_CALLBACK (modest_msg_edit_window_color_button_change),
2095 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2096 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2097 G_CALLBACK (modest_msg_edit_window_color_button_change),
2100 if (priv->current_size_index != buffer_format->font_size) {
2104 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2105 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2109 priv->current_size_index = buffer_format->font_size;
2111 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2112 markup = g_strconcat ("<span font_family='Sans'>",
2113 size_text, "</span>", NULL);
2115 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2119 gtk_tree_path_free (path);
2122 if (priv->current_face_index != buffer_format->font) {
2126 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2127 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2131 priv->current_face_index = buffer_format->font;
2132 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2133 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2134 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2141 g_free (buffer_format);
2145 #ifdef MODEST_HILDON_VERSION_0
2147 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2150 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2151 ModestMsgEditWindowPrivate *priv;
2152 GtkWidget *dialog = NULL;
2154 GdkColor *new_color = NULL;
2156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2157 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2159 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2160 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2161 g_free (buffer_format);
2163 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2164 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2165 if (new_color != NULL) {
2166 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2167 (gpointer) new_color);
2170 gtk_widget_destroy (dialog);
2175 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2178 ModestMsgEditWindowPrivate *priv;
2179 GtkWidget *dialog = NULL;
2181 GdkColor *old_color = NULL;
2182 const GdkColor *new_color = NULL;
2184 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2185 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2187 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2188 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2190 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2191 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2192 if (new_color != NULL)
2193 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2195 gtk_widget_destroy (dialog);
2201 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2204 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2205 ModestMsgEditWindowPrivate *priv;
2206 GtkWidget *dialog = NULL;
2208 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2209 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2211 dialog = hildon_color_chooser_new ();
2212 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2213 g_free (buffer_format);
2215 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2217 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2218 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2221 gtk_widget_destroy (dialog);
2226 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2229 ModestMsgEditWindowPrivate *priv;
2230 GtkWidget *dialog = NULL;
2231 GdkColor *old_color = NULL;
2233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2234 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2236 dialog = hildon_color_chooser_new ();
2237 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2239 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2241 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2242 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2244 gtk_widget_destroy (dialog);
2247 #endif /*!MODEST_HILDON_VERSION_0*/
2252 create_stream_for_uri (const gchar* uri)
2257 TnyStream *result = NULL;
2259 GnomeVFSHandle *handle = NULL;
2260 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2261 if (test == GNOME_VFS_OK) {
2262 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2263 /* Streams over OBEX (Bluetooth) are not seekable but
2264 * we expect them to be (we might need to read them
2265 * several times). So if this is a Bluetooth URI just
2266 * read the whole file into memory (this is not a fast
2267 * protocol so we can assume that these files are not
2268 * going to be very big) */
2269 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2270 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2271 TnyStream *memstream = tny_camel_mem_stream_new ();
2272 tny_stream_write_to_stream (vfssstream, memstream);
2273 g_object_unref (vfssstream);
2276 result = vfssstream;
2284 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2287 ModestMsgEditWindowPrivate *priv;
2288 GtkWidget *dialog = NULL;
2290 GSList *uris = NULL;
2291 GSList *uri_node = NULL;
2293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2295 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2296 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2297 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2299 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2301 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2302 GTK_WINDOW (dialog), GTK_WINDOW (window));
2304 response = gtk_dialog_run (GTK_DIALOG (dialog));
2306 case GTK_RESPONSE_OK:
2308 gchar *current_folder;
2309 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2310 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2311 if (current_folder && current_folder != '\0') {
2313 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2314 current_folder, &err);
2316 g_debug ("Error storing latest used folder: %s", err->message);
2320 g_free (current_folder);
2326 gtk_widget_destroy (dialog);
2328 g_object_ref (window);
2329 /* The operation could take some time so allow the dialog to be closed */
2330 while (gtk_events_pending ())
2331 gtk_main_iteration ();
2333 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2335 GnomeVFSHandle *handle = NULL;
2336 GnomeVFSResult result;
2337 GtkTextIter position;
2338 GtkTextMark *insert_mark;
2340 uri = (const gchar *) uri_node->data;
2341 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2342 if (result == GNOME_VFS_OK) {
2344 GnomeVFSFileInfo *info;
2345 gchar *filename, *basename, *escaped_filename;
2346 TnyMimePart *mime_part;
2348 const gchar *mime_type = NULL;
2349 GnomeVFSURI *vfs_uri;
2350 guint64 stream_size;
2352 gnome_vfs_close (handle);
2353 vfs_uri = gnome_vfs_uri_new (uri);
2355 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2356 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2357 g_free (escaped_filename);
2358 gnome_vfs_uri_unref (vfs_uri);
2359 info = gnome_vfs_file_info_new ();
2361 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2362 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2364 mime_type = gnome_vfs_file_info_get_mime_type (info);
2366 mime_part = tny_platform_factory_new_mime_part
2367 (modest_runtime_get_platform_factory ());
2369 TnyStream *stream = create_stream_for_uri (uri);
2371 if (stream == NULL) {
2373 modest_platform_information_banner (NULL, NULL,
2374 _FM("sfil_ib_opening_not_allowed"));
2376 g_object_unref (mime_part);
2377 gnome_vfs_file_info_unref (info);
2381 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2383 content_id = g_strdup_printf ("%d", priv->next_cid);
2384 tny_mime_part_set_content_id (mime_part, content_id);
2385 g_free (content_id);
2388 basename = g_path_get_basename (filename);
2389 tny_mime_part_set_filename (mime_part, basename);
2392 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2394 if (pixbuf != NULL) {
2395 priv->images_size += stream_size;
2396 priv->images_count ++;
2397 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2398 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2399 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2400 tny_mime_part_get_content_id (mime_part), pixbuf);
2401 g_object_unref (pixbuf);
2403 tny_list_prepend (priv->images, (GObject *) mime_part);
2404 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2406 modest_platform_information_banner (NULL, NULL,
2407 _("mail_ib_file_operation_failed"));
2411 g_object_unref (mime_part);
2412 gnome_vfs_file_info_unref (info);
2416 g_object_unref (window);
2420 on_attach_file_response (GtkDialog *dialog,
2424 GSList *uris = NULL;
2426 GnomeVFSFileSize total_size, allowed_size;
2427 ModestMsgEditWindow *window;
2428 ModestMsgEditWindowPrivate *priv;
2433 case GTK_RESPONSE_OK:
2435 gchar *current_folder;
2437 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2438 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2439 if (current_folder && current_folder != '\0') {
2441 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2442 current_folder, &err);
2444 g_debug ("Error storing latest used folder: %s", err->message);
2448 g_free (current_folder);
2455 window = MODEST_MSG_EDIT_WINDOW (user_data);
2456 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2458 /* allowed size is the maximum size - what's already there */
2459 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2460 &att_num, &att_size);
2461 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2464 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2466 const gchar *uri = (const gchar *) uri_node->data;
2469 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2471 if (total_size > allowed_size) {
2472 g_warning ("%s: total size: %u",
2473 __FUNCTION__, (unsigned int)total_size);
2476 allowed_size -= total_size;
2478 g_slist_foreach (uris, (GFunc) g_free, NULL);
2479 g_slist_free (uris);
2481 gtk_widget_destroy (GTK_WIDGET (dialog));
2485 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2487 GtkWidget *dialog = NULL;
2488 ModestMsgEditWindowPrivate *priv;
2491 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2493 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2495 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2498 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2499 GTK_FILE_CHOOSER_ACTION_OPEN);
2500 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2501 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2502 if (conf_folder && conf_folder[0] != '\0') {
2503 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2506 /* Set the default folder to images folder */
2507 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2508 ".documents", NULL);
2509 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2510 g_free (docs_folder);
2512 g_free (conf_folder);
2513 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2514 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2515 GTK_WINDOW (dialog), GTK_WINDOW (window));
2517 /* Connect to response & show */
2518 g_signal_connect (dialog, "response",
2519 G_CALLBACK (on_attach_file_response), window);
2520 gtk_widget_show (dialog);
2525 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2527 GnomeVFSFileSize allowed_size)
2530 GnomeVFSHandle *handle = NULL;
2531 ModestMsgEditWindowPrivate *priv;
2532 GnomeVFSResult result;
2533 GnomeVFSFileSize size = 0;
2534 g_return_val_if_fail (window, 0);
2535 g_return_val_if_fail (uri, 0);
2537 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2539 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2540 if (result == GNOME_VFS_OK) {
2541 TnyMimePart *mime_part;
2543 const gchar *mime_type = NULL;
2545 gchar *escaped_filename;
2548 GnomeVFSFileInfo *info;
2549 GnomeVFSURI *vfs_uri;
2551 gnome_vfs_close (handle);
2552 vfs_uri = gnome_vfs_uri_new (uri);
2555 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2556 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2557 g_free (escaped_filename);
2558 gnome_vfs_uri_unref (vfs_uri);
2560 info = gnome_vfs_file_info_new ();
2562 if (gnome_vfs_get_file_info (uri,
2564 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2566 mime_type = gnome_vfs_file_info_get_mime_type (info);
2567 mime_part = tny_platform_factory_new_mime_part
2568 (modest_runtime_get_platform_factory ());
2570 /* try to get the attachment's size; this may fail for weird
2571 * file systems, like obex, upnp... */
2572 if (allowed_size != 0 &&
2573 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2575 if (size > allowed_size) {
2576 modest_platform_information_banner (NULL, NULL,
2577 _FM("sfil_ib_opening_not_allowed"));
2582 g_warning ("%s: could not get attachment size", __FUNCTION__);
2584 stream = create_stream_for_uri (uri);
2586 if (stream == NULL) {
2588 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2590 g_object_unref (mime_part);
2592 gnome_vfs_file_info_unref (info);
2596 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2597 g_object_unref (stream);
2599 content_id = g_strdup_printf ("%d", priv->next_cid);
2600 tny_mime_part_set_content_id (mime_part, content_id);
2601 g_free (content_id);
2604 basename = g_path_get_basename (filename);
2605 tny_mime_part_set_filename (mime_part, basename);
2608 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2609 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2611 info->size == 0, info->size);
2612 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2613 gtk_widget_show_all (priv->attachments_caption);
2614 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2616 g_object_unref (mime_part);
2617 gnome_vfs_file_info_unref (info);
2624 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2627 ModestMsgEditWindowPrivate *priv;
2630 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2631 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2633 if (att_list == NULL) {
2634 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2635 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2636 g_object_unref (att_list);
2641 g_object_ref (att_list);
2644 if (tny_list_get_length (att_list) == 0) {
2645 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2647 gboolean dialog_response;
2648 gchar *message = NULL;
2649 gchar *filename = NULL;
2651 if (tny_list_get_length (att_list) == 1) {
2653 iter = tny_list_create_iterator (att_list);
2654 part = (TnyMimePart *) tny_iterator_get_current (iter);
2655 g_object_unref (iter);
2656 if (TNY_IS_MSG (part)) {
2657 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2659 filename = tny_header_dup_subject (header);
2660 g_object_unref (header);
2662 if (filename == NULL) {
2663 filename = g_strdup (_("mail_va_no_subject"));
2666 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2668 g_object_unref (part);
2670 filename = g_strdup ("");
2672 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2673 "emev_nc_delete_attachments",
2674 tny_list_get_length (att_list)), filename);
2677 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2681 if (dialog_response != GTK_RESPONSE_OK) {
2682 g_object_unref (att_list);
2686 for (iter = tny_list_create_iterator (att_list);
2687 !tny_iterator_is_done (iter);
2688 tny_iterator_next (iter)) {
2689 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2690 const gchar *att_id;
2691 tny_list_remove (priv->attachments, (GObject *) mime_part);
2693 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2695 if (tny_list_get_length (priv->attachments) == 0)
2696 gtk_widget_hide (priv->attachments_caption);
2697 att_id = tny_mime_part_get_content_id (mime_part);
2699 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2701 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2702 g_object_unref (mime_part);
2704 g_object_unref (iter);
2707 g_object_unref (att_list);
2709 /* if the last attachment has been removed, focus the Subject: field */
2710 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2711 gtk_widget_grab_focus (priv->subject_field);
2715 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2718 ModestMsgEditWindowPrivate *priv;
2719 GdkColor *new_color;
2720 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2722 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2723 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2726 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2728 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2730 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2732 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2737 font_size_clicked (GtkToolButton *button,
2738 ModestMsgEditWindow *window)
2740 ModestMsgEditWindowPrivate *priv;
2741 GtkWidget *selector, *dialog;
2743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2745 selector = hildon_touch_selector_new ();
2746 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2747 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2749 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2750 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2751 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2753 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2757 WPTextBufferFormat format;
2759 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2761 memset (&format, 0, sizeof (format));
2762 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2764 format.cs.font_size = TRUE;
2765 format.cs.text_position = TRUE;
2766 format.cs.font = TRUE;
2767 format.font_size = new_index;
2768 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2770 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2771 GINT_TO_POINTER (new_index)))
2772 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2774 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2775 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2776 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2777 size_text, "</span>", NULL);
2779 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2783 gtk_widget_destroy (dialog);
2785 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2790 font_face_clicked (GtkToolButton *button,
2791 ModestMsgEditWindow *window)
2793 ModestMsgEditWindowPrivate *priv;
2794 GtkWidget *selector, *dialog;
2795 GtkCellRenderer *renderer;
2797 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2799 selector = hildon_touch_selector_new ();
2800 renderer = gtk_cell_renderer_text_new ();
2801 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2802 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2803 renderer, "family", 0, "text", 0, NULL);
2804 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2806 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2807 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2808 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2810 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2811 gint new_font_index;
2815 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2816 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2817 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2821 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2823 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2824 GINT_TO_POINTER(new_font_index)))
2825 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2827 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2828 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2830 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2834 gtk_tree_path_free (path);
2837 gtk_widget_destroy (dialog);
2839 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2844 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2847 ModestMsgEditWindowPrivate *priv = NULL;
2848 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2850 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2851 if (!priv->update_caption_visibility)
2854 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2856 gtk_widget_show (priv->cc_caption);
2858 gtk_widget_hide (priv->cc_caption);
2860 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2864 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2867 ModestMsgEditWindowPrivate *priv = NULL;
2868 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2870 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2871 if (!priv->update_caption_visibility)
2874 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2876 gtk_widget_show (priv->bcc_caption);
2878 gtk_widget_hide (priv->bcc_caption);
2880 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2884 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2885 ModestRecptEditor *editor)
2887 ModestMsgEditWindowPrivate *priv;
2889 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2890 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2892 /* we check for low-mem; in that case, show a warning, and don't allow
2893 * for the addressbook
2895 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2898 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2900 if (editor == NULL) {
2901 GtkWidget *view_focus;
2902 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2904 /* This code should be kept in sync with ModestRecptEditor. The
2905 textview inside the recpt editor is the one that really gets the
2906 focus. As it's inside a scrolled window, and this one inside the
2907 hbox recpt editor inherits from, we'll need to go up in the
2908 hierarchy to know if the text view is part of the recpt editor
2909 or if it's a different text entry */
2911 if (gtk_widget_get_parent (view_focus)) {
2912 GtkWidget *first_parent;
2914 first_parent = gtk_widget_get_parent (view_focus);
2915 if (gtk_widget_get_parent (first_parent) &&
2916 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2917 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2922 editor = MODEST_RECPT_EDITOR (priv->to_field);
2926 modest_address_book_select_addresses (editor);
2931 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2933 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2935 modest_msg_edit_window_open_addressbook (window, NULL);
2939 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2940 gboolean show_toolbar)
2942 ModestWindowPrivate *parent_priv;
2943 ModestMsgEditWindowPrivate *priv;
2945 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2946 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2947 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2949 /* We can not just use the code of
2950 modest_msg_edit_window_setup_toolbar because it has a
2951 mixture of both initialization and creation code. */
2953 gint current_format;
2954 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2955 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2956 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2957 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2959 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2962 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2967 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2968 TnyHeaderFlags priority_flags)
2970 ModestMsgEditWindowPrivate *priv;
2971 ModestWindowPrivate *parent_priv;
2973 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2976 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2978 if (priv->priority_flags != priority_flags) {
2979 GtkAction *priority_action = NULL;
2981 priv->priority_flags = priority_flags;
2983 switch (priority_flags) {
2984 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2985 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2986 MODEST_HEADER_ICON_HIGH,
2987 HILDON_ICON_SIZE_SMALL);
2988 gtk_widget_show (priv->priority_icon);
2989 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2990 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2992 case TNY_HEADER_FLAG_LOW_PRIORITY:
2993 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2994 MODEST_HEADER_ICON_LOW,
2995 HILDON_ICON_SIZE_SMALL);
2996 gtk_widget_show (priv->priority_icon);
2997 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2998 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3001 gtk_widget_hide (priv->priority_icon);
3002 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3003 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3006 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3007 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3009 gtk_widget_queue_resize (priv->subject_box);
3013 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3016 ModestMsgEditWindowPrivate *priv;
3017 ModestWindowPrivate *parent_priv;
3018 gint current_format;
3020 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3022 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3025 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3026 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3028 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3030 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3031 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3034 if (current_format != file_format) {
3035 switch (file_format) {
3036 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3037 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3038 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3040 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3044 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3045 response = gtk_dialog_run (GTK_DIALOG (dialog));
3046 gtk_widget_destroy (dialog);
3047 if (response == GTK_RESPONSE_OK) {
3048 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3049 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3051 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3052 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3057 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3058 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3059 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3064 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3067 ModestMsgEditWindowPrivate *priv;
3068 WPTextBufferFormat oldfmt, fmt;
3069 gint old_position = 0;
3073 GdkColor *color = NULL;
3074 gboolean bold, bold_set, italic, italic_set;
3075 gboolean underline, underline_set;
3076 gboolean strikethrough, strikethrough_set;
3077 gboolean position_set;
3078 gboolean font_size_set, font_set, color_set;
3081 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3084 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3085 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3086 GTK_WINDOW(dialog), GTK_WINDOW (window));
3088 /* First we get the currently selected font information */
3089 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3091 switch (oldfmt.text_position) {
3092 case TEXT_POSITION_NORMAL:
3095 case TEXT_POSITION_SUPERSCRIPT:
3103 g_object_set (G_OBJECT (dialog),
3104 "bold", oldfmt.bold != FALSE,
3105 "bold-set", !oldfmt.cs.bold,
3106 "underline", oldfmt.underline != FALSE,
3107 "underline-set", !oldfmt.cs.underline,
3108 "italic", oldfmt.italic != FALSE,
3109 "italic-set", !oldfmt.cs.italic,
3110 "strikethrough", oldfmt.strikethrough != FALSE,
3111 "strikethrough-set", !oldfmt.cs.strikethrough,
3112 "color", &oldfmt.color,
3113 "color-set", !oldfmt.cs.color,
3114 "size", wp_font_size[oldfmt.font_size],
3115 "size-set", !oldfmt.cs.font_size,
3116 "position", old_position,
3117 "position-set", !oldfmt.cs.text_position,
3118 "family", wp_get_font_name (oldfmt.font),
3119 "family-set", !oldfmt.cs.font,
3122 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3123 GTK_WINDOW (dialog), GTK_WINDOW (window));
3124 gtk_widget_show_all (dialog);
3125 priv->font_dialog = dialog;
3126 response = gtk_dialog_run (GTK_DIALOG (dialog));
3127 priv->font_dialog = NULL;
3128 if (response == GTK_RESPONSE_OK) {
3130 g_object_get( dialog,
3132 "bold-set", &bold_set,
3133 "underline", &underline,
3134 "underline-set", &underline_set,
3136 "italic-set", &italic_set,
3137 "strikethrough", &strikethrough,
3138 "strikethrough-set", &strikethrough_set,
3140 "color-set", &color_set,
3142 "size-set", &font_size_set,
3143 "family", &font_name,
3144 "family-set", &font_set,
3145 "position", &position,
3146 "position-set", &position_set,
3151 if (response == GTK_RESPONSE_OK) {
3152 memset(&fmt, 0, sizeof(fmt));
3158 fmt.italic = italic;
3159 fmt.cs.italic = TRUE;
3161 if (underline_set) {
3162 fmt.underline = underline;
3163 fmt.cs.underline = TRUE;
3165 if (strikethrough_set) {
3166 fmt.strikethrough = strikethrough;
3167 fmt.cs.strikethrough = TRUE;
3172 ? TEXT_POSITION_NORMAL
3173 : ( ( position == 1 )
3174 ? TEXT_POSITION_SUPERSCRIPT
3175 : TEXT_POSITION_SUBSCRIPT );
3176 fmt.cs.text_position = TRUE;
3177 fmt.font_size = oldfmt.font_size;
3181 fmt.cs.color = TRUE;
3184 fmt.font = wp_get_font_index(font_name,
3189 if (font_size_set) {
3190 fmt.cs.font_size = TRUE;
3191 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3193 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3194 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3196 gtk_widget_destroy (dialog);
3198 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3202 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3204 ModestMsgEditWindowPrivate *priv;
3206 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3207 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3209 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3211 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3212 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3216 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3218 ModestMsgEditWindowPrivate *priv;
3220 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3221 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3223 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3225 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3226 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3231 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3233 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3235 priv->can_undo = can_undo;
3239 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3241 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3243 priv->can_redo = can_redo;
3247 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3249 ModestMsgEditWindowPrivate *priv;
3250 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3251 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3253 return priv->can_undo;
3257 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3259 ModestMsgEditWindowPrivate *priv;
3260 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3261 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3263 return priv->can_redo;
3268 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3271 GtkTextIter match_start, match_end;
3273 if (image_id == NULL)
3276 gtk_text_buffer_get_start_iter (buffer, &iter);
3278 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3279 GSList *tags = gtk_text_iter_get_tags (&match_start);
3281 for (node = tags; node != NULL; node = g_slist_next (node)) {
3282 GtkTextTag *tag = (GtkTextTag *) node->data;
3283 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3284 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3285 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3287 offset = gtk_text_iter_get_offset (&match_start);
3288 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3289 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3293 gtk_text_iter_forward_char (&iter);
3298 message_is_empty (ModestMsgEditWindow *window)
3300 ModestMsgEditWindowPrivate *priv = NULL;
3302 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3303 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3305 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3306 * so we can ignore markup.
3308 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3311 count = gtk_text_buffer_get_char_count (buf);
3317 msg_body_focus (GtkWidget *focus,
3318 GdkEventFocus *event,
3322 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3323 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3324 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3329 recpt_field_changed (GtkTextBuffer *buffer,
3330 ModestMsgEditWindow *editor)
3332 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3333 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3337 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3339 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3340 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3344 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3347 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3348 GtkTextBuffer *buffer;
3350 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3351 gtk_text_buffer_set_modified (buffer, modified);
3352 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3353 gtk_text_buffer_set_modified (buffer, modified);
3354 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3355 gtk_text_buffer_set_modified (buffer, modified);
3356 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3360 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3362 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3363 const char *account_name;
3364 GtkTextBuffer *buffer;
3366 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3367 if (gtk_text_buffer_get_modified (buffer))
3369 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3370 if (gtk_text_buffer_get_modified (buffer))
3372 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3373 if (gtk_text_buffer_get_modified (buffer))
3375 if (gtk_text_buffer_get_modified (priv->text_buffer))
3378 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3379 if (priv->original_mailbox) {
3380 if (!account_name || strcmp (account_name, priv->original_mailbox))
3382 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3393 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3395 ModestMsgEditWindowPrivate *priv = NULL;
3397 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3398 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3400 /* check if there's no recipient added */
3401 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3402 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3403 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3404 /* no recipient contents, then select contacts */
3405 modest_msg_edit_window_open_addressbook (window, NULL);
3409 g_object_ref (window);
3410 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3411 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3412 g_object_unref (window);
3415 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3416 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3417 g_object_unref (window);
3420 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3421 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3422 g_object_unref (window);
3426 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3427 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3428 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3429 g_object_unref (window);
3436 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3437 ModestMsgEditWindow *window)
3439 modest_msg_edit_window_offer_attach_file (window);
3443 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3445 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3447 return priv->clipboard_text;
3451 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3453 ModestMsgEditWindow *window)
3455 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3456 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3459 /* It could happen that the window was already closed */
3460 if (!GTK_WIDGET_VISIBLE (window))
3463 g_object_ref (window);
3464 text = gtk_clipboard_wait_for_text (selection_clipboard);
3466 if (priv->clipboard_text != NULL) {
3467 g_free (priv->clipboard_text);
3469 priv->clipboard_text = text;
3471 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3473 g_object_unref (window);
3476 static gboolean clipboard_owner_change_idle (gpointer userdata)
3478 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3479 ModestMsgEditWindowPrivate *priv;
3481 gdk_threads_enter ();
3482 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3483 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3485 priv->clipboard_owner_idle = 0;
3486 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3487 gdk_threads_leave ();
3493 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3495 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3496 if (priv->clipboard_owner_idle == 0) {
3497 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3498 clipboard_owner_change_idle,
3499 g_object_ref (window),
3505 subject_field_move_cursor (GtkEntry *entry,
3506 GtkMovementStep step,
3511 /* It could happen that the window was already closed */
3512 if (!GTK_WIDGET_VISIBLE (window))
3515 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3519 update_window_title (ModestMsgEditWindow *window)
3521 ModestMsgEditWindowPrivate *priv = NULL;
3522 const gchar *subject;
3524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3525 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3526 if (subject == NULL || subject[0] == '\0')
3527 subject = _("mail_va_new_email");
3529 gtk_window_set_title (GTK_WINDOW (window), subject);
3535 body_insert_text (GtkTextBuffer *buffer,
3536 GtkTextIter *location,
3539 ModestMsgEditWindow *window)
3541 GtkTextIter end_iter;
3544 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3546 offset = gtk_text_iter_get_offset (&end_iter);
3548 if (offset + len > MAX_BODY_LENGTH) {
3549 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3550 if (offset < MAX_BODY_LENGTH)
3554 /* Prevent endless recursion */
3555 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3556 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3557 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3558 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3560 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3564 if (offset + len > MAX_BODY_LENGTH) {
3565 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3566 _CS("ckdg_ib_maximum_characters_reached"));
3571 subject_field_changed (GtkEditable *editable,
3572 ModestMsgEditWindow *window)
3574 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3575 update_window_title (window);
3576 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3577 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3578 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3581 subject_field_insert_text (GtkEditable *editable,
3583 gint new_text_length,
3585 ModestMsgEditWindow *window)
3587 GString *result = g_string_new ("");
3589 gint result_len = 0;
3590 const gchar *entry_text = NULL;
3593 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3594 old_length = g_utf8_strlen (entry_text, -1);
3596 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3597 gunichar c = g_utf8_get_char_validated (current, 8);
3598 /* Invalid unichar, stop */
3604 result = g_string_append_unichar (result, c);
3608 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3609 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3612 /* Prevent endless recursion */
3613 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3614 g_signal_emit_by_name (editable, "insert-text",
3615 (gpointer) result->str, (gpointer) result->len,
3616 (gpointer) position, (gpointer) window);
3617 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3621 if (result_len + old_length > 1000) {
3622 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3623 _CS("ckdg_ib_maximum_characters_reached"));
3625 g_string_free (result, TRUE);
3629 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3632 ModestMsgEditWindowPrivate *priv = NULL;
3634 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3637 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3640 gtk_widget_show_all (priv->find_toolbar);
3641 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3643 gtk_widget_hide_all (priv->find_toolbar);
3644 gtk_widget_grab_focus (priv->msg_body);
3649 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3651 GtkTextIter *match_start,
3652 GtkTextIter *match_end)
3654 GtkTextIter end_iter;
3655 gchar *str_casefold;
3658 gchar *range_casefold;
3661 gboolean result = FALSE;
3668 gtk_text_iter_forward_to_end (&end_iter);
3670 str_casefold = g_utf8_casefold (str, -1);
3671 str_chars_n = strlen (str);
3673 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3674 range_casefold = g_utf8_casefold (range_text, -1);
3675 range_chars_n = strlen (range_casefold);
3677 if (range_chars_n < str_chars_n) {
3678 g_free (str_casefold);
3679 g_free (range_text);
3680 g_free (range_casefold);
3684 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3685 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3686 if (!g_utf8_collate (range_subtext, str_casefold)) {
3687 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3689 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3690 match_start, match_end, NULL)) {
3691 g_warning ("Matched string with collate, but not matched in model");
3693 g_free (found_text);
3695 g_free (range_subtext);
3699 g_free (str_casefold);
3700 g_free (range_text);
3701 g_free (range_casefold);
3708 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3709 ModestMsgEditWindow *window)
3711 gchar *current_search = NULL;
3712 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3714 GtkTextIter selection_start, selection_end;
3715 GtkTextIter match_start, match_end;
3716 gboolean continue_search = FALSE;
3718 if (message_is_empty (window)) {
3719 g_free (priv->last_search);
3720 priv->last_search = NULL;
3721 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3725 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3726 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3727 g_free (current_search);
3728 g_free (priv->last_search);
3729 priv->last_search = NULL;
3730 /* Information banner about empty search */
3731 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3735 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3736 continue_search = TRUE;
3738 g_free (priv->last_search);
3739 priv->last_search = g_strdup (current_search);
3742 if (continue_search) {
3743 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3744 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3745 &match_start, &match_end);
3747 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3749 GtkTextIter buffer_start;
3750 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3751 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3752 &match_start, &match_end);
3754 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3757 /* Mark as selected the string found in search */
3759 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3760 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3761 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3763 g_free (priv->last_search);
3764 priv->last_search = NULL;
3766 g_free (current_search);
3770 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3772 ModestMsgEditWindowPrivate *priv;
3774 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3779 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3782 ModestMsgEditWindowPrivate *priv;
3784 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3789 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3790 ModestMsgEditWindow *window)
3792 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3796 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3799 ModestMsgEditWindowPrivate *priv;
3800 TnyHeader *header = NULL;
3802 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3803 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3807 if (priv->draft_msg != NULL) {
3808 g_object_unref (priv->draft_msg);
3811 if (draft != NULL) {
3812 g_object_ref (draft);
3813 header = tny_msg_get_header (draft);
3814 if (priv->msg_uid) {
3815 g_free (priv->msg_uid);
3816 priv->msg_uid = NULL;
3818 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3821 priv->draft_msg = draft;
3825 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3826 GtkTextIter *start, GtkTextIter *end,
3829 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3830 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3833 if (tag == NULL) return;
3834 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3835 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3836 replace_with_images (window, priv->images);
3841 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3844 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3846 g_return_if_fail (TNY_IS_MIME_PART (part));
3847 tny_list_prepend (priv->attachments, (GObject *) part);
3848 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3849 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3850 gtk_widget_show_all (priv->attachments_caption);
3851 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3855 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3857 ModestMsgEditWindowPrivate *priv;
3859 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3862 return priv->msg_uid;
3866 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3867 ModestMsgEditWindowWidgetType widget_type)
3869 ModestMsgEditWindowPrivate *priv;
3871 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3874 switch (widget_type) {
3875 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3876 return priv->msg_body;
3878 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3879 return priv->to_field;
3881 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3882 return priv->cc_field;
3884 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3885 return priv->bcc_field;
3887 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3888 return priv->subject_field;
3890 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3891 return priv->attachments_view;
3899 remove_tags (WPTextBuffer *buffer)
3901 GtkTextIter start, end;
3903 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3904 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3906 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3910 on_account_removed (TnyAccountStore *account_store,
3911 TnyAccount *account,
3914 /* Do nothing if it's a store account, because we use the
3915 transport to send the messages */
3916 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3917 const gchar *parent_acc = NULL;
3918 const gchar *our_acc = NULL;
3920 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3921 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3922 /* Close this window if I'm showing a message of the removed account */
3923 if (strcmp (parent_acc, our_acc) == 0)
3924 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3928 static void update_signature (ModestMsgEditWindow *self,
3929 const gchar *old_account,
3930 const gchar *new_account)
3932 ModestMsgEditWindowPrivate *priv;
3933 gboolean has_old_signature, has_new_signature;
3935 GtkTextIter match_start, match_end;
3936 ModestAccountMgr *mgr;
3938 gchar *full_signature;
3940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3942 gtk_text_buffer_begin_user_action (priv->text_buffer);
3944 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3945 mgr = modest_runtime_get_account_mgr ();
3949 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3950 if (has_old_signature) {
3951 full_signature = g_strconcat ("\n--\n", signature, NULL);
3952 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3953 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3955 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3956 &match_start, &match_end, NULL)) {
3959 g_free (full_signature);
3964 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3965 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3966 if (has_new_signature) {
3967 full_signature = g_strconcat ("\n--\n", signature, NULL);
3968 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3969 g_free (full_signature);
3972 gtk_text_buffer_end_user_action (priv->text_buffer);
3976 from_field_changed (HildonPickerButton *button,
3977 ModestMsgEditWindow *self)
3979 ModestMsgEditWindowPrivate *priv;
3980 gchar *old_account, *new_account;
3982 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3984 old_account = priv->last_from_account;
3985 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3986 new_account = priv->last_from_account;
3988 update_signature (self, old_account, new_account);
3992 typedef struct _MessageSettingsHelper {
3993 ModestMsgEditWindow *window;
3994 GSList *priority_group;
3995 GSList *format_group;
3996 GtkToggleButton *current_priority;
3997 GtkToggleButton *current_format;
3998 } MessageSettingsHelper;
4001 on_priority_toggle (GtkToggleButton *button,
4002 MessageSettingsHelper *helper)
4005 ModestMsgEditWindowPrivate *priv;
4007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4008 if (gtk_toggle_button_get_active (button)) {
4010 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4011 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4012 if ((node_button != button) &&
4013 gtk_toggle_button_get_active (node_button)) {
4014 gtk_toggle_button_set_active (node_button, FALSE);
4017 helper->current_priority = button;
4019 gboolean found = FALSE;
4020 /* If no one is active, activate it again */
4021 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4022 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4023 if (gtk_toggle_button_get_active (node_button)) {
4029 gtk_toggle_button_set_active (button, TRUE);
4035 on_format_toggle (GtkToggleButton *button,
4036 MessageSettingsHelper *helper)
4039 ModestMsgEditWindowPrivate *priv;
4041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4042 if (gtk_toggle_button_get_active (button)) {
4044 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4045 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4046 if ((node_button != button) &&
4047 gtk_toggle_button_get_active (node_button)) {
4048 gtk_toggle_button_set_active (node_button, FALSE);
4051 helper->current_format = button;
4053 gboolean found = FALSE;
4054 /* If no one is active, activate it again */
4055 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4056 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4057 if (gtk_toggle_button_get_active (node_button)) {
4063 gtk_toggle_button_set_active (button, TRUE);
4070 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4075 GtkWidget *priority_hbox;
4076 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4077 GtkWidget *captioned;
4078 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4079 GtkWidget *format_hbox;
4080 GtkWidget *html_toggle, *text_toggle;
4081 ModestMsgEditWindowPrivate *priv;
4082 MessageSettingsHelper helper = {0,};
4084 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4086 helper.window = window;
4087 helper.priority_group = NULL;
4088 helper.format_group = NULL;
4090 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4091 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4093 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4094 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4095 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4096 vbox = gtk_vbox_new (FALSE, 0);
4097 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4098 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4099 gtk_container_add (GTK_CONTAINER (align), vbox);
4100 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4101 gtk_widget_show (align);
4102 gtk_widget_show (vbox);
4104 /* Priority toggles */
4105 priority_hbox = gtk_hbox_new (TRUE, 0);
4106 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4107 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4108 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4109 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4110 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4111 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4112 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4113 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4114 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4115 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4116 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4117 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4118 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4119 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4120 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4121 gtk_widget_show_all (priority_hbox);
4122 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4123 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4124 gtk_widget_show (captioned);
4125 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4127 /* format toggles */
4128 format_hbox = gtk_hbox_new (TRUE, 0);
4129 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4130 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4131 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4132 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4133 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4134 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4135 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4136 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4137 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4138 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4139 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4140 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4141 gtk_widget_show_all (format_hbox);
4142 gtk_widget_show (format_hbox);
4143 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4146 g_object_unref (title_sizegroup);
4147 g_object_unref (value_sizegroup);
4149 /* Set current values */
4150 switch (priv->priority_flags) {
4151 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4152 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4153 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4155 case TNY_HEADER_FLAG_LOW_PRIORITY:
4156 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4157 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4160 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4161 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4165 switch (modest_msg_edit_window_get_format (window)) {
4166 case MODEST_MSG_EDIT_FORMAT_TEXT:
4167 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4168 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4170 case MODEST_MSG_EDIT_FORMAT_HTML:
4172 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4173 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4177 /* Signal connects */
4178 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4179 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4180 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4181 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4182 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4184 /* Save settings if the user clicked on done */
4185 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4186 TnyHeaderFlags flags;
4187 ModestMsgEditFormat old_format, new_format;
4189 /* Set priority flags */
4190 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4191 if (priv->priority_flags != flags)
4192 modest_msg_edit_window_set_priority_flags (window, flags);
4194 /* Set edit format */
4195 old_format = modest_msg_edit_window_get_format (window);
4196 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4197 if (old_format != new_format) {
4198 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4199 modest_msg_edit_window_set_file_format (window, file_format);
4203 gtk_widget_destroy (dialog);
4204 g_slist_free (helper.priority_group);
4208 on_message_settings (GtkAction *action,
4209 ModestMsgEditWindow *window)
4211 modest_msg_edit_window_show_msg_settings_dialog (window);
4215 on_cc_button_toggled (HildonCheckButton *button,
4216 ModestMsgEditWindow *window)
4218 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4220 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4221 hildon_check_button_get_active (button));
4225 on_bcc_button_toggled (HildonCheckButton *button,
4226 ModestMsgEditWindow *window)
4228 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4230 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4231 hildon_check_button_get_active (button));
4235 setup_menu (ModestMsgEditWindow *self)
4237 ModestMsgEditWindowPrivate *priv = NULL;
4239 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4241 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4243 /* Settings menu buttons */
4244 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4245 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4247 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4248 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4249 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4251 priv->cc_button = hildon_check_button_new (0);
4252 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4253 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4255 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4257 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4258 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4259 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4260 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4262 priv->bcc_button = hildon_check_button_new (0);
4263 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4264 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4266 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4268 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4269 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4270 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4271 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4273 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4274 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4275 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4276 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: add attachment"), NULL,
4277 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4279 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4280 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4281 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4282 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4283 APP_MENU_CALLBACK (on_message_settings),
4285 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4286 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4291 emit_open_addressbook (GtkButton *button,
4292 ModestRecptEditor *editor)
4294 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4298 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4299 const gchar *label, GtkWidget *control)
4301 GtkWidget *abook_button;
4304 GtkWidget *label_widget;
4306 box = gtk_hbox_new (FALSE, 0);
4308 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4309 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4311 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4312 label_widget = gtk_label_new (label);
4313 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4314 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4316 gtk_container_add (GTK_CONTAINER (align), abook_button);
4317 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4318 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4319 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4320 if (title_size_group)
4321 gtk_size_group_add_widget (title_size_group, label_widget);
4322 if (value_size_group)
4323 gtk_size_group_add_widget (value_size_group, control);
4325 g_signal_connect (G_OBJECT (abook_button), "clicked",
4326 G_CALLBACK (emit_open_addressbook), control);