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;
806 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
807 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
809 parent_priv->ui_manager = gtk_ui_manager_new();
810 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
811 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
813 /* Add common actions */
814 gtk_action_group_add_actions (action_group,
815 modest_msg_edit_action_entries,
816 G_N_ELEMENTS (modest_msg_edit_action_entries),
818 gtk_action_group_add_actions (action_group,
819 hildon2_msg_edit_action_entries,
820 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
822 gtk_action_group_add_toggle_actions (action_group,
823 modest_msg_edit_toggle_action_entries,
824 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
826 gtk_action_group_add_radio_actions (action_group,
827 modest_msg_edit_alignment_radio_action_entries,
828 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
830 G_CALLBACK (modest_ui_actions_on_change_justify),
832 gtk_action_group_add_radio_actions (action_group,
833 modest_msg_edit_priority_action_entries,
834 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
836 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
838 gtk_action_group_add_radio_actions (action_group,
839 modest_msg_edit_file_format_action_entries,
840 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
841 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
842 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
844 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
845 g_object_unref (action_group);
847 /* Load the UI definition */
848 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
851 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
852 g_clear_error (&error);
855 /* Add accelerators */
856 gtk_window_add_accel_group (GTK_WINDOW (obj),
857 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
859 parent_priv->menubar = NULL;
861 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
862 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
864 /* Note: This ModestPairList* must exist for as long as the picker
865 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
866 * so it can't know how to manage its memory. */
867 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
868 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
870 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
871 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
872 _("mail_va_from"), priv->from_field);
873 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
874 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
875 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
877 priv->to_field = modest_recpt_editor_new ();
878 priv->cc_field = modest_recpt_editor_new ();
879 priv->bcc_field = modest_recpt_editor_new ();
880 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
881 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
882 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
883 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
884 priv->priority_icon = gtk_image_new ();
885 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
886 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
887 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
888 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
889 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
890 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
891 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
892 priv->attachments_view = modest_attachments_view_new (NULL);
893 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
894 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
896 priv->header_box = gtk_vbox_new (FALSE, 0);
898 to_caption = _create_addressbook_box
899 (title_size_group, value_size_group,
900 _("mail_va_to"), priv->to_field);
901 priv->cc_caption = _create_addressbook_box
902 (title_size_group, value_size_group,
903 _("mail_va_cc"), priv->cc_field);
904 priv->bcc_caption = _create_addressbook_box
905 (title_size_group, value_size_group,
906 _("mail_va_hotfix1"), priv->bcc_field);
907 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
908 _("mail_va_subject"), FALSE, priv->subject_box);
909 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
910 _("mail_va_attachment"),
912 priv->attachments_view,
913 HILDON_SIZE_AUTO_WIDTH |
914 HILDON_SIZE_AUTO_HEIGHT);
915 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
916 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
917 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
918 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 118, -1);
920 g_object_unref (title_size_group);
921 g_object_unref (value_size_group);
923 from_send_hbox = gtk_hbox_new (FALSE, 0);
924 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
925 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
927 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
928 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
929 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
930 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
931 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
932 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
933 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
935 init_wp_text_view_style ();
937 priv->msg_body = modest_wp_text_view_new ();
940 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
941 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
942 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
943 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
944 #if (GTK_MINOR_VERSION >= 10)
945 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
946 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
948 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
949 deserialize_type, TRUE);
951 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
953 priv->find_toolbar = hildon_find_toolbar_new (NULL);
954 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
956 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
958 priv->pannable = hildon_pannable_area_new ();
960 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
962 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
963 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
964 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
966 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
967 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
968 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
970 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
971 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
973 window_box = gtk_vbox_new (FALSE, 0);
974 gtk_container_add (GTK_CONTAINER(obj), window_box);
976 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
978 /* Set window icon */
979 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
981 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
982 g_object_unref (window_icon);
987 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
989 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
991 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
992 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
993 priv->clipboard_change_handler_id))
994 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
995 priv->clipboard_change_handler_id);
996 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
997 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
998 priv->default_clipboard_change_handler_id))
999 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1000 priv->default_clipboard_change_handler_id);
1002 if (priv->account_removed_handler_id &&
1003 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1004 priv->account_removed_handler_id))
1005 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1006 priv->account_removed_handler_id);
1010 modest_msg_edit_window_finalize (GObject *obj)
1012 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1014 /* Sanity check: shouldn't be needed, the window mgr should
1015 call this function before */
1016 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1018 if (priv->font_dialog != NULL) {
1019 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1022 if (priv->clipboard_text != NULL) {
1023 g_free (priv->clipboard_text);
1024 priv->clipboard_text = NULL;
1027 if (priv->draft_msg != NULL) {
1028 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1029 if (TNY_IS_HEADER (header)) {
1030 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1031 modest_window_mgr_unregister_header (mgr, header);
1033 g_object_unref (priv->draft_msg);
1034 priv->draft_msg = NULL;
1036 if (priv->outbox_msg != NULL) {
1037 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1038 if (TNY_IS_HEADER (header)) {
1039 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1040 modest_window_mgr_unregister_header (mgr, header);
1042 g_object_unref (priv->outbox_msg);
1043 priv->outbox_msg = NULL;
1045 if (priv->correct_scroll_idle > 0) {
1046 g_source_remove (priv->correct_scroll_idle);
1047 priv->correct_scroll_idle = 0;
1049 if (priv->scroll_drag_timeout_id > 0) {
1050 g_source_remove (priv->scroll_drag_timeout_id);
1051 priv->scroll_drag_timeout_id = 0;
1053 if (priv->clipboard_owner_idle > 0) {
1054 g_source_remove (priv->clipboard_owner_idle);
1055 priv->clipboard_owner_idle = 0;
1057 if (priv->original_account_name)
1058 g_free (priv->original_account_name);
1059 if (priv->original_mailbox)
1060 g_free (priv->original_mailbox);
1061 g_free (priv->msg_uid);
1062 g_free (priv->last_search);
1063 g_free (priv->references);
1064 g_free (priv->in_reply_to);
1065 g_object_unref (priv->faces_model);
1066 g_object_unref (priv->sizes_model);
1067 g_object_unref (priv->attachments);
1068 g_object_unref (priv->images);
1070 /* This had to stay alive for as long as the picker that used it: */
1071 modest_pair_list_free (priv->from_field_protos);
1073 G_OBJECT_CLASS(parent_class)->finalize (obj);
1077 pixbuf_size_prepared (GdkPixbufLoader *loader,
1080 ModestMsgEditWindow *self)
1082 gint new_height, new_width;
1085 new_height = height;
1089 if (width > IMAGE_MAX_WIDTH) {
1090 new_height = height * IMAGE_MAX_WIDTH / width;
1091 new_width = IMAGE_MAX_WIDTH;
1094 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1098 pixbuf_from_stream (TnyStream *stream,
1099 const gchar *mime_type,
1100 guint64 *stream_size,
1101 ModestMsgEditWindow *self)
1103 GdkPixbufLoader *loader;
1106 GError *error = NULL;
1110 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1112 if (loader == NULL) {
1117 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1119 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1121 tny_stream_reset (TNY_STREAM (stream));
1122 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1123 unsigned char read_buffer[128];
1125 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1127 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1130 /* Allow some UI responsiveness */
1131 while (gtk_events_pending ())
1132 gtk_main_iteration ();
1134 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1136 gdk_pixbuf_loader_close (loader, &error);
1139 g_error_free (error);
1140 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1142 g_object_ref (pixbuf);
1143 g_object_unref (loader);
1148 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1149 GdkPixbuf *new_pixbuf;
1151 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1152 gdk_pixbuf_get_width (pixbuf);
1153 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1154 g_object_unref (pixbuf);
1155 pixbuf = new_pixbuf;
1159 *stream_size = size;
1165 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1167 ModestMsgEditWindowPrivate *priv;
1170 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1172 g_object_ref (self);
1173 for (iter = tny_list_create_iterator (attachments);
1174 !tny_iterator_is_done (iter);
1175 tny_iterator_next (iter)) {
1176 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1177 const gchar *cid = tny_mime_part_get_content_id (part);
1178 const gchar *mime_type = tny_mime_part_get_content_type (part);
1179 if ((cid != NULL)&&(mime_type != NULL)) {
1180 guint64 stream_size;
1181 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1182 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1185 g_object_unref (stream);
1187 if (pixbuf != NULL) {
1188 priv->images_count ++;
1189 priv->images_size += stream_size;
1190 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1191 g_object_unref (pixbuf);
1194 g_object_unref (part);
1196 g_object_unref (iter);
1197 g_object_unref (self);
1201 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1203 TnyMimePart *parent = NULL;
1204 const gchar *content_type = NULL;
1205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1207 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1209 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1210 parent = g_object_ref (msg);
1211 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1212 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1215 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1216 iter = tny_list_create_iterator (parts);
1217 while (!tny_iterator_is_done (iter)) {
1219 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1220 content_type = tny_mime_part_get_content_type (part);
1221 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1225 g_object_unref (part);
1227 tny_iterator_next (iter);
1229 g_object_unref (iter);
1230 g_object_unref (parts);
1233 if (parent != NULL) {
1234 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1237 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1238 iter = tny_list_create_iterator (parts);
1239 while (!tny_iterator_is_done (iter)) {
1241 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1242 content_type = tny_mime_part_get_content_type (part);
1243 if (content_type && g_str_has_prefix (content_type, "image/")) {
1244 tny_list_prepend (priv->images, (GObject *) part);
1246 g_object_unref (part);
1247 tny_iterator_next (iter);
1249 g_object_unref (iter);
1250 g_object_unref (parts);
1251 g_object_unref (parent);
1256 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1259 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1261 for (iter = tny_list_create_iterator (attachments) ;
1262 !tny_iterator_is_done (iter);
1263 tny_iterator_next (iter)) {
1264 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1265 const gchar *cid = tny_mime_part_get_content_id (part);
1267 char *invalid = NULL;
1268 gint int_cid = strtol (cid, &invalid, 10);
1269 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1270 priv->next_cid = int_cid + 1;
1273 g_object_unref (part);
1275 g_object_unref (iter);
1279 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1282 gchar *to, *cc, *bcc, *subject;
1284 ModestMsgEditWindowPrivate *priv;
1285 ModestWindowPrivate *parent_priv;
1287 TnyHeaderFlags priority_flags;
1288 TnyFolder *msg_folder;
1289 gboolean is_html = FALSE;
1290 gboolean field_view_set;
1292 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1293 g_return_if_fail (TNY_IS_MSG (msg));
1295 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1296 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1298 header = tny_msg_get_header (msg);
1299 to = tny_header_dup_to (header);
1300 cc = tny_header_dup_cc (header);
1301 bcc = tny_header_dup_bcc (header);
1302 subject = tny_header_dup_subject (header);
1304 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1305 priority_flags = tny_header_get_priority (header);
1308 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1310 field_view_set = TRUE;
1312 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1313 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1314 gtk_widget_show (priv->cc_caption);
1315 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1316 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1317 gtk_widget_hide (priv->cc_caption);
1318 field_view_set = FALSE;
1320 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1322 field_view_set = TRUE;
1324 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1325 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1326 gtk_widget_show (priv->bcc_caption);
1327 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1328 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1329 gtk_widget_hide (priv->bcc_caption);
1330 field_view_set = FALSE;
1332 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1336 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1337 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1340 update_window_title (self);
1342 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1343 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1345 if ((body == NULL)||(body[0] == '\0')) {
1347 body = modest_text_utils_convert_to_html ("");
1350 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1351 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1354 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1357 /* Add attachments to the view */
1358 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1359 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1360 if (tny_list_get_length (priv->attachments) == 0) {
1361 gtk_widget_hide (priv->attachments_caption);
1363 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1364 gtk_widget_show_all (priv->attachments_caption);
1366 get_related_images (self, msg);
1367 update_next_cid (self, priv->attachments);
1368 update_next_cid (self, priv->images);
1369 replace_with_images (self, priv->images);
1371 if (preserve_is_rich && !is_html) {
1372 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1373 /* Get the default format required from configuration */
1374 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1375 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1378 /* Set the default focus depending on having already a To: field or not */
1379 if ((!to)||(*to == '\0')) {
1380 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1382 gtk_widget_grab_focus (priv->msg_body);
1385 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1387 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1388 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1390 modest_msg_edit_window_set_modified (self, FALSE);
1392 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1393 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1394 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1395 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1397 if (priv->msg_uid) {
1398 g_free (priv->msg_uid);
1399 priv->msg_uid = NULL;
1402 /* we should set a reference to the incoming message if it is a draft */
1403 msg_folder = tny_msg_get_folder (msg);
1405 if (modest_tny_folder_is_local_folder (msg_folder)) {
1406 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1407 if (type == TNY_FOLDER_TYPE_INVALID)
1408 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1410 if (type == TNY_FOLDER_TYPE_DRAFTS)
1411 priv->draft_msg = g_object_ref(msg);
1412 if (type == TNY_FOLDER_TYPE_OUTBOX)
1413 priv->outbox_msg = g_object_ref(msg);
1414 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1416 g_object_unref (msg_folder);
1427 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1429 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1430 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1431 GtkWidget *placeholder;
1432 GtkWidget *tool_item;
1437 GtkWidget *sizes_menu;
1438 GtkWidget *fonts_menu;
1444 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1445 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1446 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1447 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1449 /* Font color placeholder */
1450 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1451 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1454 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1455 priv->font_color_button = hildon_color_button_new ();
1456 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1457 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1458 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1459 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1462 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1463 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1465 G_CALLBACK (modest_msg_edit_window_color_button_change),
1468 /* Font size and face placeholder */
1469 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1470 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1472 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1473 priv->size_tool_button_label = gtk_label_new (NULL);
1474 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1475 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1476 size_text, "</span>", NULL);
1477 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1478 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1480 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1481 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1482 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1483 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1484 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1485 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1486 gtk_widget_set_sensitive (arrow, FALSE);
1487 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1488 sizes_menu = gtk_menu_new ();
1489 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1490 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1493 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1494 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1496 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1500 if (wp_font_size[size_index] == 12)
1501 priv->current_size_index = size_index;
1505 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1506 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1507 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1508 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1509 priv->font_size_toolitem = tool_item;
1512 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1513 priv->font_tool_button_label = gtk_label_new (NULL);
1514 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1515 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1516 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1518 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1519 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1520 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1521 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1522 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1523 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1524 gtk_widget_set_sensitive (arrow, FALSE);
1525 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1526 fonts_menu = gtk_menu_new ();
1527 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1528 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1531 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1533 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1534 0, wp_get_font_name (font_index),
1537 if (font_index == DEFAULT_FONT)
1538 priv->current_face_index = font_index;
1540 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1541 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1542 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1543 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1544 priv->font_face_toolitem = tool_item;
1546 /* Set expand and homogeneous for remaining items */
1547 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1548 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1549 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1550 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1551 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1552 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1553 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1554 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1555 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1557 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1558 will not show the tool items added to the placeholders) */
1559 gtk_widget_show_all (parent_priv->toolbar);
1561 /* Set the no show all *after* showing all items. We do not
1562 want the toolbar to be shown with a show all because it
1563 could go agains the gconf setting regarding showing or not
1564 the toolbar of the editor window */
1565 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1571 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1574 ModestWindowPrivate *parent_priv;
1575 ModestMsgEditWindowPrivate *priv;
1576 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1577 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1578 ModestWindowMgr *mgr = NULL;
1580 g_return_val_if_fail (msg, NULL);
1581 g_return_val_if_fail (account_name, NULL);
1583 mgr = modest_runtime_get_window_mgr ();
1585 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1588 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1590 /* Menubar. Update the state of some toggles */
1591 priv->from_field_protos = get_transports ();
1592 priv->original_mailbox = NULL;
1593 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1594 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1595 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1596 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1597 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1598 priv->original_mailbox = g_strdup (mailbox);
1599 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1600 /* We set the first mailbox as the active mailbox */
1601 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1602 if (priv->original_mailbox != NULL)
1603 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1604 (gpointer) priv->original_mailbox);
1606 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1607 (gpointer) account_name);
1609 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1611 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1612 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1614 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1615 hildon_touch_selector_get_current_text
1616 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1617 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1618 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1621 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1623 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1625 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1626 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1628 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1630 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1631 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1632 /* Add common dimming rules */
1633 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1634 modest_msg_edit_window_toolbar_dimming_entries,
1635 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1636 MODEST_WINDOW (obj));
1637 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1638 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1639 MODEST_WINDOW (obj));
1640 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1641 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1642 MODEST_WINDOW (obj));
1643 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1644 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1645 MODEST_WINDOW (obj));
1646 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1647 G_CALLBACK (modest_ui_dimming_rules_on_send),
1648 MODEST_WINDOW (obj));
1649 /* Insert dimming rules group for this window */
1650 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1651 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1653 /* Setup app menu */
1654 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1656 /* Checks the dimming rules */
1657 g_object_unref (toolbar_rules_group);
1658 g_object_unref (clipboard_rules_group);
1659 gtk_widget_hide (priv->priority_icon);
1660 gtk_widget_queue_resize (priv->subject_box);
1661 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1663 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1665 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1666 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1667 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1668 priv->update_caption_visibility = TRUE;
1670 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1672 /* Track account-removed signal, this window should be closed
1673 in the case we're creating a mail associated to the account
1675 priv->account_removed_handler_id =
1676 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1678 G_CALLBACK(on_account_removed),
1681 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1683 return (ModestWindow*) obj;
1687 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1689 GString **string_buffer = (GString **) user_data;
1691 *string_buffer = g_string_append (*string_buffer, buffer);
1697 * @result: A new string which should be freed with g_free().
1700 get_formatted_data (ModestMsgEditWindow *edit_window)
1702 ModestMsgEditWindowPrivate *priv;
1703 GString *string_buffer = g_string_new ("");
1705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1707 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1709 modest_text_utils_hyperlinkify (string_buffer);
1711 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1713 return g_string_free (string_buffer, FALSE);
1718 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1721 const gchar *account_name;
1722 ModestMsgEditWindowPrivate *priv;
1723 TnyIterator *att_iter;
1724 const gchar *picker_active_id;
1726 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1730 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1731 g_return_val_if_fail (picker_active_id, NULL);
1732 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1734 /* don't free these (except from) */
1735 data = g_slice_new0 (MsgData);
1736 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1737 data->account_name = g_strdup (account_name);
1738 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1739 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1740 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1741 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1742 data->references = g_strdup (priv->references);
1743 data->in_reply_to = g_strdup (priv->in_reply_to);
1744 if (priv->draft_msg) {
1745 data->draft_msg = g_object_ref (priv->draft_msg);
1746 } else if (priv->outbox_msg) {
1747 data->draft_msg = g_object_ref (priv->outbox_msg);
1749 data->draft_msg = NULL;
1752 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1754 gtk_text_buffer_get_bounds (buf, &b, &e);
1755 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1757 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1758 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1760 data->html_body = NULL;
1762 /* deep-copy the data */
1763 att_iter = tny_list_create_iterator (priv->attachments);
1764 data->attachments = NULL;
1765 while (!tny_iterator_is_done (att_iter)) {
1766 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1767 if (!(TNY_IS_MIME_PART(part))) {
1768 g_warning ("strange data in attachment list");
1769 g_object_unref (part);
1770 tny_iterator_next (att_iter);
1773 data->attachments = g_list_append (data->attachments,
1775 tny_iterator_next (att_iter);
1777 g_object_unref (att_iter);
1779 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1780 att_iter = tny_list_create_iterator (priv->images);
1781 data->images = NULL;
1782 while (!tny_iterator_is_done (att_iter)) {
1783 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1785 if (!(TNY_IS_MIME_PART(part))) {
1786 g_warning ("strange data in attachment list");
1787 g_object_unref (part);
1788 tny_iterator_next (att_iter);
1791 cid = tny_mime_part_get_content_id (part);
1793 gchar *image_tag_id;
1794 GtkTextTag *image_tag;
1796 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1797 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1798 g_free (image_tag_id);
1800 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1802 ((gtk_text_iter_has_tag (&iter, image_tag))||
1803 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1804 data->images = g_list_append (data->images,
1805 g_object_ref (part));
1807 g_object_unref (part);
1808 tny_iterator_next (att_iter);
1810 g_object_unref (att_iter);
1812 data->priority_flags = priv->priority_flags;
1819 unref_gobject (GObject *obj, gpointer data)
1821 if (!G_IS_OBJECT(obj))
1823 g_object_unref (obj);
1827 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1830 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1838 g_free (data->from);
1839 g_free (data->subject);
1840 g_free (data->plain_body);
1841 g_free (data->html_body);
1842 g_free (data->account_name);
1843 g_free (data->references);
1844 g_free (data->in_reply_to);
1846 if (data->draft_msg != NULL) {
1847 g_object_unref (data->draft_msg);
1848 data->draft_msg = NULL;
1851 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1852 g_list_free (data->attachments);
1853 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1854 g_list_free (data->images);
1856 g_slice_free (MsgData, data);
1860 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1862 guint64 *parts_size)
1864 ModestMsgEditWindowPrivate *priv;
1866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1868 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1870 /* TODO: add images */
1871 *parts_size += priv->images_size;
1872 *parts_count += priv->images_count;
1877 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1880 ModestMsgEditWindowPrivate *priv = NULL;
1881 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1883 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1885 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1887 return MODEST_MSG_EDIT_FORMAT_HTML;
1889 return MODEST_MSG_EDIT_FORMAT_TEXT;
1893 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1894 ModestMsgEditFormat format)
1896 ModestMsgEditWindowPrivate *priv;
1898 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1899 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1902 case MODEST_MSG_EDIT_FORMAT_HTML:
1903 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1905 case MODEST_MSG_EDIT_FORMAT_TEXT:
1906 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1909 g_return_if_reached ();
1913 ModestMsgEditFormatState *
1914 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1916 ModestMsgEditFormatState *format_state = NULL;
1917 ModestMsgEditWindowPrivate *priv;
1918 WPTextBufferFormat *buffer_format;
1920 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1922 buffer_format = g_new0 (WPTextBufferFormat, 1);
1923 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1925 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1927 format_state = g_new0 (ModestMsgEditFormatState, 1);
1928 format_state->bold = buffer_format->bold&0x1;
1929 format_state->italics = buffer_format->italic&0x1;
1930 format_state->bullet = buffer_format->bullet&0x1;
1931 format_state->color = buffer_format->color;
1932 format_state->font_size = buffer_format->font_size;
1933 format_state->font_family = wp_get_font_name (buffer_format->font);
1934 format_state->justification = buffer_format->justification;
1935 g_free (buffer_format);
1937 return format_state;
1942 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1943 const ModestMsgEditFormatState *format_state)
1945 ModestMsgEditWindowPrivate *priv;
1946 WPTextBufferFormat *buffer_format;
1947 WPTextBufferFormat *current_format;
1949 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1950 g_return_if_fail (format_state != NULL);
1952 buffer_format = g_new0 (WPTextBufferFormat, 1);
1953 current_format = g_new0 (WPTextBufferFormat, 1);
1955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1956 gtk_widget_grab_focus (priv->msg_body);
1957 buffer_format->bold = (format_state->bold != FALSE);
1958 buffer_format->italic = (format_state->italics != FALSE);
1959 buffer_format->color = format_state->color;
1960 buffer_format->font_size = format_state->font_size;
1961 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1962 buffer_format->justification = format_state->justification;
1963 buffer_format->bullet = format_state->bullet;
1965 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1967 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1968 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1969 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1970 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1971 buffer_format->cs.font = (buffer_format->font != current_format->font);
1972 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1973 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1975 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1976 if (buffer_format->cs.bold) {
1977 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1978 GINT_TO_POINTER (buffer_format->bold&0x1));
1980 if (buffer_format->cs.italic) {
1981 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1982 GINT_TO_POINTER (buffer_format->italic&0x1));
1984 if (buffer_format->cs.color) {
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1986 GINT_TO_POINTER (&(buffer_format->color)));
1988 if (buffer_format->cs.font_size) {
1989 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1990 GINT_TO_POINTER (buffer_format->font_size));
1992 if (buffer_format->cs.justification) {
1993 switch (buffer_format->justification) {
1994 case GTK_JUSTIFY_LEFT:
1995 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1996 GINT_TO_POINTER(TRUE));
1998 case GTK_JUSTIFY_CENTER:
1999 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2000 GINT_TO_POINTER(TRUE));
2002 case GTK_JUSTIFY_RIGHT:
2003 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2004 GINT_TO_POINTER(TRUE));
2011 if (buffer_format->cs.font) {
2012 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2013 GINT_TO_POINTER (buffer_format->font));
2015 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2016 if (buffer_format->cs.bullet) {
2017 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2018 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2020 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2022 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2024 g_free (buffer_format);
2025 g_free (current_format);
2027 /* Check dimming rules */
2028 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2029 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2033 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2035 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2037 ModestWindowPrivate *parent_priv;
2038 ModestMsgEditWindowPrivate *priv;
2040 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2043 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2044 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2045 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2046 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2048 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2049 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2050 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2053 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2055 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2056 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2058 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2059 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2061 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2062 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2065 switch (buffer_format->justification)
2067 case GTK_JUSTIFY_LEFT:
2068 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2070 case GTK_JUSTIFY_CENTER:
2071 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2073 case GTK_JUSTIFY_RIGHT:
2074 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2081 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2083 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2084 G_CALLBACK (modest_msg_edit_window_color_button_change),
2086 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2087 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2088 G_CALLBACK (modest_msg_edit_window_color_button_change),
2091 if (priv->current_size_index != buffer_format->font_size) {
2095 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2096 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2100 priv->current_size_index = buffer_format->font_size;
2102 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2103 markup = g_strconcat ("<span font_family='Sans'>",
2104 size_text, "</span>", NULL);
2106 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2110 gtk_tree_path_free (path);
2113 if (priv->current_face_index != buffer_format->font) {
2117 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2118 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2122 priv->current_face_index = buffer_format->font;
2123 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2124 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2125 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2132 g_free (buffer_format);
2136 #ifdef MODEST_HILDON_VERSION_0
2138 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2141 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2142 ModestMsgEditWindowPrivate *priv;
2143 GtkWidget *dialog = NULL;
2145 GdkColor *new_color = NULL;
2147 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2148 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2150 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2151 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2152 g_free (buffer_format);
2154 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2155 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2156 if (new_color != NULL) {
2157 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2158 (gpointer) new_color);
2161 gtk_widget_destroy (dialog);
2166 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2169 ModestMsgEditWindowPrivate *priv;
2170 GtkWidget *dialog = NULL;
2172 GdkColor *old_color = NULL;
2173 const GdkColor *new_color = NULL;
2175 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2176 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2178 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2179 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2181 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2182 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2183 if (new_color != NULL)
2184 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2186 gtk_widget_destroy (dialog);
2192 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2195 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2196 ModestMsgEditWindowPrivate *priv;
2197 GtkWidget *dialog = NULL;
2199 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2200 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2202 dialog = hildon_color_chooser_new ();
2203 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2204 g_free (buffer_format);
2206 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2208 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2209 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2212 gtk_widget_destroy (dialog);
2217 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2220 ModestMsgEditWindowPrivate *priv;
2221 GtkWidget *dialog = NULL;
2222 GdkColor *old_color = NULL;
2224 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2225 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2227 dialog = hildon_color_chooser_new ();
2228 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2230 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2232 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2233 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2235 gtk_widget_destroy (dialog);
2238 #endif /*!MODEST_HILDON_VERSION_0*/
2243 create_stream_for_uri (const gchar* uri)
2248 TnyStream *result = NULL;
2250 GnomeVFSHandle *handle = NULL;
2251 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2252 if (test == GNOME_VFS_OK) {
2253 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2254 /* Streams over OBEX (Bluetooth) are not seekable but
2255 * we expect them to be (we might need to read them
2256 * several times). So if this is a Bluetooth URI just
2257 * read the whole file into memory (this is not a fast
2258 * protocol so we can assume that these files are not
2259 * going to be very big) */
2260 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2261 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2262 TnyStream *memstream = tny_camel_mem_stream_new ();
2263 tny_stream_write_to_stream (vfssstream, memstream);
2264 g_object_unref (vfssstream);
2267 result = vfssstream;
2275 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2278 ModestMsgEditWindowPrivate *priv;
2279 GtkWidget *dialog = NULL;
2281 GSList *uris = NULL;
2282 GSList *uri_node = NULL;
2284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2286 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2287 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2288 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2290 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2292 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2293 GTK_WINDOW (dialog), GTK_WINDOW (window));
2295 response = gtk_dialog_run (GTK_DIALOG (dialog));
2297 case GTK_RESPONSE_OK:
2299 gchar *current_folder;
2300 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2301 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2302 if (current_folder && current_folder != '\0') {
2304 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2305 current_folder, &err);
2307 g_debug ("Error storing latest used folder: %s", err->message);
2311 g_free (current_folder);
2317 gtk_widget_destroy (dialog);
2319 g_object_ref (window);
2320 /* The operation could take some time so allow the dialog to be closed */
2321 while (gtk_events_pending ())
2322 gtk_main_iteration ();
2324 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2326 GnomeVFSHandle *handle = NULL;
2327 GnomeVFSResult result;
2328 GtkTextIter position;
2329 GtkTextMark *insert_mark;
2331 uri = (const gchar *) uri_node->data;
2332 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2333 if (result == GNOME_VFS_OK) {
2335 GnomeVFSFileInfo *info;
2336 gchar *filename, *basename, *escaped_filename;
2337 TnyMimePart *mime_part;
2339 const gchar *mime_type = NULL;
2340 GnomeVFSURI *vfs_uri;
2341 guint64 stream_size;
2343 gnome_vfs_close (handle);
2344 vfs_uri = gnome_vfs_uri_new (uri);
2346 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2347 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2348 g_free (escaped_filename);
2349 gnome_vfs_uri_unref (vfs_uri);
2350 info = gnome_vfs_file_info_new ();
2352 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2353 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2355 mime_type = gnome_vfs_file_info_get_mime_type (info);
2357 mime_part = tny_platform_factory_new_mime_part
2358 (modest_runtime_get_platform_factory ());
2360 TnyStream *stream = create_stream_for_uri (uri);
2362 if (stream == NULL) {
2364 modest_platform_information_banner (NULL, NULL,
2365 _FM("sfil_ib_opening_not_allowed"));
2367 g_object_unref (mime_part);
2368 gnome_vfs_file_info_unref (info);
2372 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2374 content_id = g_strdup_printf ("%d", priv->next_cid);
2375 tny_mime_part_set_content_id (mime_part, content_id);
2376 g_free (content_id);
2379 basename = g_path_get_basename (filename);
2380 tny_mime_part_set_filename (mime_part, basename);
2383 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2385 if (pixbuf != NULL) {
2386 priv->images_size += stream_size;
2387 priv->images_count ++;
2388 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2389 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2390 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2391 tny_mime_part_get_content_id (mime_part), pixbuf);
2392 g_object_unref (pixbuf);
2394 tny_list_prepend (priv->images, (GObject *) mime_part);
2395 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2397 modest_platform_information_banner (NULL, NULL,
2398 _("mail_ib_file_operation_failed"));
2402 g_object_unref (mime_part);
2403 gnome_vfs_file_info_unref (info);
2407 g_object_unref (window);
2411 on_attach_file_response (GtkDialog *dialog,
2415 GSList *uris = NULL;
2417 GnomeVFSFileSize total_size, allowed_size;
2418 ModestMsgEditWindow *window;
2419 ModestMsgEditWindowPrivate *priv;
2424 case GTK_RESPONSE_OK:
2426 gchar *current_folder;
2428 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2429 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2430 if (current_folder && current_folder != '\0') {
2432 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2433 current_folder, &err);
2435 g_debug ("Error storing latest used folder: %s", err->message);
2439 g_free (current_folder);
2446 window = MODEST_MSG_EDIT_WINDOW (user_data);
2447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2449 /* allowed size is the maximum size - what's already there */
2450 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2451 &att_num, &att_size);
2452 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2455 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2457 const gchar *uri = (const gchar *) uri_node->data;
2460 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2462 if (total_size > allowed_size) {
2463 g_warning ("%s: total size: %u",
2464 __FUNCTION__, (unsigned int)total_size);
2467 allowed_size -= total_size;
2469 g_slist_foreach (uris, (GFunc) g_free, NULL);
2470 g_slist_free (uris);
2472 gtk_widget_destroy (GTK_WIDGET (dialog));
2476 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2478 GtkWidget *dialog = NULL;
2479 ModestMsgEditWindowPrivate *priv;
2482 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2486 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2489 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2490 GTK_FILE_CHOOSER_ACTION_OPEN);
2491 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2492 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2493 if (conf_folder && conf_folder[0] != '\0') {
2494 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2497 /* Set the default folder to images folder */
2498 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2499 ".documents", NULL);
2500 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2501 g_free (docs_folder);
2503 g_free (conf_folder);
2504 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2505 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2506 GTK_WINDOW (dialog), GTK_WINDOW (window));
2508 /* Connect to response & show */
2509 g_signal_connect (dialog, "response",
2510 G_CALLBACK (on_attach_file_response), window);
2511 gtk_widget_show (dialog);
2516 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2518 GnomeVFSFileSize allowed_size)
2521 GnomeVFSHandle *handle = NULL;
2522 ModestMsgEditWindowPrivate *priv;
2523 GnomeVFSResult result;
2524 GnomeVFSFileSize size = 0;
2525 g_return_val_if_fail (window, 0);
2526 g_return_val_if_fail (uri, 0);
2528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2530 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2531 if (result == GNOME_VFS_OK) {
2532 TnyMimePart *mime_part;
2534 const gchar *mime_type = NULL;
2536 gchar *escaped_filename;
2539 GnomeVFSFileInfo *info;
2540 GnomeVFSURI *vfs_uri;
2542 gnome_vfs_close (handle);
2543 vfs_uri = gnome_vfs_uri_new (uri);
2546 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2547 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2548 g_free (escaped_filename);
2549 gnome_vfs_uri_unref (vfs_uri);
2551 info = gnome_vfs_file_info_new ();
2553 if (gnome_vfs_get_file_info (uri,
2555 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2557 mime_type = gnome_vfs_file_info_get_mime_type (info);
2558 mime_part = tny_platform_factory_new_mime_part
2559 (modest_runtime_get_platform_factory ());
2561 /* try to get the attachment's size; this may fail for weird
2562 * file systems, like obex, upnp... */
2563 if (allowed_size != 0 &&
2564 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2566 if (size > allowed_size) {
2567 modest_platform_information_banner (NULL, NULL,
2568 _FM("sfil_ib_opening_not_allowed"));
2573 g_warning ("%s: could not get attachment size", __FUNCTION__);
2575 stream = create_stream_for_uri (uri);
2577 if (stream == NULL) {
2579 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2581 g_object_unref (mime_part);
2583 gnome_vfs_file_info_unref (info);
2587 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2588 g_object_unref (stream);
2590 content_id = g_strdup_printf ("%d", priv->next_cid);
2591 tny_mime_part_set_content_id (mime_part, content_id);
2592 g_free (content_id);
2595 basename = g_path_get_basename (filename);
2596 tny_mime_part_set_filename (mime_part, basename);
2599 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2600 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2602 info->size == 0, info->size);
2603 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2604 gtk_widget_show_all (priv->attachments_caption);
2605 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2607 g_object_unref (mime_part);
2608 gnome_vfs_file_info_unref (info);
2615 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2618 ModestMsgEditWindowPrivate *priv;
2621 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2622 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2624 if (att_list == NULL) {
2625 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2626 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2627 g_object_unref (att_list);
2632 g_object_ref (att_list);
2635 if (tny_list_get_length (att_list) == 0) {
2636 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2638 gboolean dialog_response;
2639 gchar *message = NULL;
2640 gchar *filename = NULL;
2642 if (tny_list_get_length (att_list) == 1) {
2644 iter = tny_list_create_iterator (att_list);
2645 part = (TnyMimePart *) tny_iterator_get_current (iter);
2646 g_object_unref (iter);
2647 if (TNY_IS_MSG (part)) {
2648 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2650 filename = tny_header_dup_subject (header);
2651 g_object_unref (header);
2653 if (filename == NULL) {
2654 filename = g_strdup (_("mail_va_no_subject"));
2657 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2659 g_object_unref (part);
2661 filename = g_strdup ("");
2663 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2664 "emev_nc_delete_attachments",
2665 tny_list_get_length (att_list)), filename);
2668 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2672 if (dialog_response != GTK_RESPONSE_OK) {
2673 g_object_unref (att_list);
2677 for (iter = tny_list_create_iterator (att_list);
2678 !tny_iterator_is_done (iter);
2679 tny_iterator_next (iter)) {
2680 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2681 const gchar *att_id;
2682 tny_list_remove (priv->attachments, (GObject *) mime_part);
2684 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2686 if (tny_list_get_length (priv->attachments) == 0)
2687 gtk_widget_hide (priv->attachments_caption);
2688 att_id = tny_mime_part_get_content_id (mime_part);
2690 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2692 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2693 g_object_unref (mime_part);
2695 g_object_unref (iter);
2698 g_object_unref (att_list);
2700 /* if the last attachment has been removed, focus the Subject: field */
2701 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2702 gtk_widget_grab_focus (priv->subject_field);
2706 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2709 ModestMsgEditWindowPrivate *priv;
2710 GdkColor *new_color;
2711 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2713 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2714 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2717 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2719 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2721 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2723 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2728 font_size_clicked (GtkToolButton *button,
2729 ModestMsgEditWindow *window)
2731 ModestMsgEditWindowPrivate *priv;
2732 GtkWidget *selector, *dialog;
2734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2736 selector = hildon_touch_selector_new ();
2737 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2738 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2740 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2741 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2742 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2744 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2748 WPTextBufferFormat format;
2750 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2752 memset (&format, 0, sizeof (format));
2753 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2755 format.cs.font_size = TRUE;
2756 format.cs.text_position = TRUE;
2757 format.cs.font = TRUE;
2758 format.font_size = new_index;
2759 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2761 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2762 GINT_TO_POINTER (new_index)))
2763 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2765 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2766 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2767 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2768 size_text, "</span>", NULL);
2770 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2774 gtk_widget_destroy (dialog);
2776 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2781 font_face_clicked (GtkToolButton *button,
2782 ModestMsgEditWindow *window)
2784 ModestMsgEditWindowPrivate *priv;
2785 GtkWidget *selector, *dialog;
2786 GtkCellRenderer *renderer;
2788 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2790 selector = hildon_touch_selector_new ();
2791 renderer = gtk_cell_renderer_text_new ();
2792 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2793 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2794 renderer, "family", 0, "text", 0, NULL);
2795 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2797 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2798 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2799 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2801 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2802 gint new_font_index;
2806 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2807 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2808 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2812 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2814 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2815 GINT_TO_POINTER(new_font_index)))
2816 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2818 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2819 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2821 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2825 gtk_tree_path_free (path);
2828 gtk_widget_destroy (dialog);
2830 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2835 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2838 ModestMsgEditWindowPrivate *priv = NULL;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2841 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2842 if (!priv->update_caption_visibility)
2845 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2847 gtk_widget_show (priv->cc_caption);
2849 gtk_widget_hide (priv->cc_caption);
2851 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2855 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2858 ModestMsgEditWindowPrivate *priv = NULL;
2859 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2862 if (!priv->update_caption_visibility)
2865 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2867 gtk_widget_show (priv->bcc_caption);
2869 gtk_widget_hide (priv->bcc_caption);
2871 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2875 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2876 ModestRecptEditor *editor)
2878 ModestMsgEditWindowPrivate *priv;
2880 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2881 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2883 /* we check for low-mem; in that case, show a warning, and don't allow
2884 * for the addressbook
2886 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2889 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2891 if (editor == NULL) {
2892 GtkWidget *view_focus;
2893 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2895 /* This code should be kept in sync with ModestRecptEditor. The
2896 textview inside the recpt editor is the one that really gets the
2897 focus. As it's inside a scrolled window, and this one inside the
2898 hbox recpt editor inherits from, we'll need to go up in the
2899 hierarchy to know if the text view is part of the recpt editor
2900 or if it's a different text entry */
2902 if (gtk_widget_get_parent (view_focus)) {
2903 GtkWidget *first_parent;
2905 first_parent = gtk_widget_get_parent (view_focus);
2906 if (gtk_widget_get_parent (first_parent) &&
2907 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2908 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2913 editor = MODEST_RECPT_EDITOR (priv->to_field);
2917 modest_address_book_select_addresses (editor);
2922 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2924 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2926 modest_msg_edit_window_open_addressbook (window, NULL);
2930 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2931 gboolean show_toolbar)
2933 ModestWindowPrivate *parent_priv;
2935 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2936 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2938 /* We can not just use the code of
2939 modest_msg_edit_window_setup_toolbar because it has a
2940 mixture of both initialization and creation code. */
2942 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2944 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2948 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2949 TnyHeaderFlags priority_flags)
2951 ModestMsgEditWindowPrivate *priv;
2952 ModestWindowPrivate *parent_priv;
2954 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2956 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2957 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2959 if (priv->priority_flags != priority_flags) {
2960 GtkAction *priority_action = NULL;
2962 priv->priority_flags = priority_flags;
2964 switch (priority_flags) {
2965 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2966 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2967 MODEST_HEADER_ICON_HIGH,
2968 HILDON_ICON_SIZE_SMALL);
2969 gtk_widget_show (priv->priority_icon);
2970 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2971 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2973 case TNY_HEADER_FLAG_LOW_PRIORITY:
2974 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2975 MODEST_HEADER_ICON_LOW,
2976 HILDON_ICON_SIZE_SMALL);
2977 gtk_widget_show (priv->priority_icon);
2978 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2979 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2982 gtk_widget_hide (priv->priority_icon);
2983 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2984 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2987 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2988 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2990 gtk_widget_queue_resize (priv->subject_box);
2994 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2997 ModestMsgEditWindowPrivate *priv;
2998 ModestWindowPrivate *parent_priv;
2999 gint current_format;
3001 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3003 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3004 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3006 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3007 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3009 if (current_format != file_format) {
3010 switch (file_format) {
3011 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3012 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3013 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3015 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3019 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3020 response = gtk_dialog_run (GTK_DIALOG (dialog));
3021 gtk_widget_destroy (dialog);
3022 if (response == GTK_RESPONSE_OK) {
3023 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3025 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3026 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3031 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3032 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3033 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3038 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3041 ModestMsgEditWindowPrivate *priv;
3042 WPTextBufferFormat oldfmt, fmt;
3043 gint old_position = 0;
3047 GdkColor *color = NULL;
3048 gboolean bold, bold_set, italic, italic_set;
3049 gboolean underline, underline_set;
3050 gboolean strikethrough, strikethrough_set;
3051 gboolean position_set;
3052 gboolean font_size_set, font_set, color_set;
3055 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3056 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3058 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3059 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3060 GTK_WINDOW(dialog), GTK_WINDOW (window));
3062 /* First we get the currently selected font information */
3063 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3065 switch (oldfmt.text_position) {
3066 case TEXT_POSITION_NORMAL:
3069 case TEXT_POSITION_SUPERSCRIPT:
3077 g_object_set (G_OBJECT (dialog),
3078 "bold", oldfmt.bold != FALSE,
3079 "bold-set", !oldfmt.cs.bold,
3080 "underline", oldfmt.underline != FALSE,
3081 "underline-set", !oldfmt.cs.underline,
3082 "italic", oldfmt.italic != FALSE,
3083 "italic-set", !oldfmt.cs.italic,
3084 "strikethrough", oldfmt.strikethrough != FALSE,
3085 "strikethrough-set", !oldfmt.cs.strikethrough,
3086 "color", &oldfmt.color,
3087 "color-set", !oldfmt.cs.color,
3088 "size", wp_font_size[oldfmt.font_size],
3089 "size-set", !oldfmt.cs.font_size,
3090 "position", old_position,
3091 "position-set", !oldfmt.cs.text_position,
3092 "family", wp_get_font_name (oldfmt.font),
3093 "family-set", !oldfmt.cs.font,
3096 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3097 GTK_WINDOW (dialog), GTK_WINDOW (window));
3098 gtk_widget_show_all (dialog);
3099 priv->font_dialog = dialog;
3100 response = gtk_dialog_run (GTK_DIALOG (dialog));
3101 priv->font_dialog = NULL;
3102 if (response == GTK_RESPONSE_OK) {
3104 g_object_get( dialog,
3106 "bold-set", &bold_set,
3107 "underline", &underline,
3108 "underline-set", &underline_set,
3110 "italic-set", &italic_set,
3111 "strikethrough", &strikethrough,
3112 "strikethrough-set", &strikethrough_set,
3114 "color-set", &color_set,
3116 "size-set", &font_size_set,
3117 "family", &font_name,
3118 "family-set", &font_set,
3119 "position", &position,
3120 "position-set", &position_set,
3125 if (response == GTK_RESPONSE_OK) {
3126 memset(&fmt, 0, sizeof(fmt));
3132 fmt.italic = italic;
3133 fmt.cs.italic = TRUE;
3135 if (underline_set) {
3136 fmt.underline = underline;
3137 fmt.cs.underline = TRUE;
3139 if (strikethrough_set) {
3140 fmt.strikethrough = strikethrough;
3141 fmt.cs.strikethrough = TRUE;
3146 ? TEXT_POSITION_NORMAL
3147 : ( ( position == 1 )
3148 ? TEXT_POSITION_SUPERSCRIPT
3149 : TEXT_POSITION_SUBSCRIPT );
3150 fmt.cs.text_position = TRUE;
3151 fmt.font_size = oldfmt.font_size;
3155 fmt.cs.color = TRUE;
3158 fmt.font = wp_get_font_index(font_name,
3163 if (font_size_set) {
3164 fmt.cs.font_size = TRUE;
3165 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3167 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3168 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3170 gtk_widget_destroy (dialog);
3172 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3176 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3178 ModestMsgEditWindowPrivate *priv;
3180 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3181 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3183 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3185 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3186 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3190 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3192 ModestMsgEditWindowPrivate *priv;
3194 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3195 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3197 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3199 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3200 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3205 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3207 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3209 priv->can_undo = can_undo;
3213 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3215 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3217 priv->can_redo = can_redo;
3221 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3223 ModestMsgEditWindowPrivate *priv;
3224 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3225 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3227 return priv->can_undo;
3231 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3233 ModestMsgEditWindowPrivate *priv;
3234 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3235 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 return priv->can_redo;
3242 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3245 GtkTextIter match_start, match_end;
3247 if (image_id == NULL)
3250 gtk_text_buffer_get_start_iter (buffer, &iter);
3252 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3253 GSList *tags = gtk_text_iter_get_tags (&match_start);
3255 for (node = tags; node != NULL; node = g_slist_next (node)) {
3256 GtkTextTag *tag = (GtkTextTag *) node->data;
3257 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3258 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3259 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3261 offset = gtk_text_iter_get_offset (&match_start);
3262 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3263 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3267 gtk_text_iter_forward_char (&iter);
3272 message_is_empty (ModestMsgEditWindow *window)
3274 ModestMsgEditWindowPrivate *priv = NULL;
3276 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3277 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3279 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3280 * so we can ignore markup.
3282 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3285 count = gtk_text_buffer_get_char_count (buf);
3291 msg_body_focus (GtkWidget *focus,
3292 GdkEventFocus *event,
3296 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3297 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3298 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3303 recpt_field_changed (GtkTextBuffer *buffer,
3304 ModestMsgEditWindow *editor)
3306 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3307 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3311 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3313 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3314 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3318 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3321 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3322 GtkTextBuffer *buffer;
3324 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3325 gtk_text_buffer_set_modified (buffer, modified);
3326 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3327 gtk_text_buffer_set_modified (buffer, modified);
3328 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3329 gtk_text_buffer_set_modified (buffer, modified);
3330 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3334 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3336 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3337 const char *account_name;
3338 GtkTextBuffer *buffer;
3340 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3341 if (gtk_text_buffer_get_modified (buffer))
3343 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3344 if (gtk_text_buffer_get_modified (buffer))
3346 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3347 if (gtk_text_buffer_get_modified (buffer))
3349 if (gtk_text_buffer_get_modified (priv->text_buffer))
3352 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3353 if (priv->original_mailbox) {
3354 if (!account_name || strcmp (account_name, priv->original_mailbox))
3356 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3367 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3369 ModestMsgEditWindowPrivate *priv = NULL;
3371 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3372 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3374 /* check if there's no recipient added */
3375 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3376 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3377 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3378 /* no recipient contents, then select contacts */
3379 modest_msg_edit_window_open_addressbook (window, NULL);
3383 g_object_ref (window);
3384 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3385 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3386 g_object_unref (window);
3389 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3390 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3391 g_object_unref (window);
3394 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3395 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3396 g_object_unref (window);
3400 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3401 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3402 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3403 g_object_unref (window);
3410 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3411 ModestMsgEditWindow *window)
3413 modest_msg_edit_window_offer_attach_file (window);
3417 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3419 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3421 return priv->clipboard_text;
3425 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3427 ModestMsgEditWindow *window)
3429 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3430 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3433 /* It could happen that the window was already closed */
3434 if (!GTK_WIDGET_VISIBLE (window))
3437 g_object_ref (window);
3438 text = gtk_clipboard_wait_for_text (selection_clipboard);
3440 if (priv->clipboard_text != NULL) {
3441 g_free (priv->clipboard_text);
3443 priv->clipboard_text = text;
3445 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3447 g_object_unref (window);
3450 static gboolean clipboard_owner_change_idle (gpointer userdata)
3452 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3453 ModestMsgEditWindowPrivate *priv;
3455 gdk_threads_enter ();
3456 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3457 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3459 priv->clipboard_owner_idle = 0;
3460 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3461 gdk_threads_leave ();
3467 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3469 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3470 if (priv->clipboard_owner_idle == 0) {
3471 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3472 clipboard_owner_change_idle,
3473 g_object_ref (window),
3479 subject_field_move_cursor (GtkEntry *entry,
3480 GtkMovementStep step,
3485 /* It could happen that the window was already closed */
3486 if (!GTK_WIDGET_VISIBLE (window))
3489 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3493 update_window_title (ModestMsgEditWindow *window)
3495 ModestMsgEditWindowPrivate *priv = NULL;
3496 const gchar *subject;
3498 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3499 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3500 if (subject == NULL || subject[0] == '\0')
3501 subject = _("mail_va_new_email");
3503 gtk_window_set_title (GTK_WINDOW (window), subject);
3509 body_insert_text (GtkTextBuffer *buffer,
3510 GtkTextIter *location,
3513 ModestMsgEditWindow *window)
3515 GtkTextIter end_iter;
3518 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3520 offset = gtk_text_iter_get_offset (&end_iter);
3522 if (offset + len > MAX_BODY_LENGTH) {
3523 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3524 if (offset < MAX_BODY_LENGTH)
3528 /* Prevent endless recursion */
3529 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3530 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3531 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3532 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3534 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3538 if (offset + len > MAX_BODY_LENGTH) {
3539 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3540 _CS("ckdg_ib_maximum_characters_reached"));
3545 subject_field_changed (GtkEditable *editable,
3546 ModestMsgEditWindow *window)
3548 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3549 update_window_title (window);
3550 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3551 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3552 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3555 subject_field_insert_text (GtkEditable *editable,
3557 gint new_text_length,
3559 ModestMsgEditWindow *window)
3561 GString *result = g_string_new ("");
3563 gint result_len = 0;
3564 const gchar *entry_text = NULL;
3567 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3568 old_length = g_utf8_strlen (entry_text, -1);
3570 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3571 gunichar c = g_utf8_get_char_validated (current, 8);
3572 /* Invalid unichar, stop */
3578 result = g_string_append_unichar (result, c);
3582 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3583 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3586 /* Prevent endless recursion */
3587 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3588 g_signal_emit_by_name (editable, "insert-text",
3589 (gpointer) result->str, (gpointer) result->len,
3590 (gpointer) position, (gpointer) window);
3591 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3595 if (result_len + old_length > 1000) {
3596 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3597 _CS("ckdg_ib_maximum_characters_reached"));
3599 g_string_free (result, TRUE);
3603 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3606 ModestMsgEditWindowPrivate *priv = NULL;
3608 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3611 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3614 gtk_widget_show_all (priv->find_toolbar);
3615 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3617 gtk_widget_hide_all (priv->find_toolbar);
3618 gtk_widget_grab_focus (priv->msg_body);
3623 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3625 GtkTextIter *match_start,
3626 GtkTextIter *match_end)
3628 GtkTextIter end_iter;
3629 gchar *str_casefold;
3632 gchar *range_casefold;
3635 gboolean result = FALSE;
3642 gtk_text_iter_forward_to_end (&end_iter);
3644 str_casefold = g_utf8_casefold (str, -1);
3645 str_chars_n = strlen (str);
3647 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3648 range_casefold = g_utf8_casefold (range_text, -1);
3649 range_chars_n = strlen (range_casefold);
3651 if (range_chars_n < str_chars_n) {
3652 g_free (str_casefold);
3653 g_free (range_text);
3654 g_free (range_casefold);
3658 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3659 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3660 if (!g_utf8_collate (range_subtext, str_casefold)) {
3661 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3663 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3664 match_start, match_end, NULL)) {
3665 g_warning ("Matched string with collate, but not matched in model");
3667 g_free (found_text);
3669 g_free (range_subtext);
3673 g_free (str_casefold);
3674 g_free (range_text);
3675 g_free (range_casefold);
3682 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3683 ModestMsgEditWindow *window)
3685 gchar *current_search = NULL;
3686 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3688 GtkTextIter selection_start, selection_end;
3689 GtkTextIter match_start, match_end;
3690 gboolean continue_search = FALSE;
3692 if (message_is_empty (window)) {
3693 g_free (priv->last_search);
3694 priv->last_search = NULL;
3695 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3699 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3700 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3701 g_free (current_search);
3702 g_free (priv->last_search);
3703 priv->last_search = NULL;
3704 /* Information banner about empty search */
3705 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3709 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3710 continue_search = TRUE;
3712 g_free (priv->last_search);
3713 priv->last_search = g_strdup (current_search);
3716 if (continue_search) {
3717 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3718 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3719 &match_start, &match_end);
3721 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3723 GtkTextIter buffer_start;
3724 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3725 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3726 &match_start, &match_end);
3728 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3731 /* Mark as selected the string found in search */
3733 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3734 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3735 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3737 g_free (priv->last_search);
3738 priv->last_search = NULL;
3740 g_free (current_search);
3744 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3746 ModestMsgEditWindowPrivate *priv;
3748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3753 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3756 ModestMsgEditWindowPrivate *priv;
3758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3763 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3764 ModestMsgEditWindow *window)
3766 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3770 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3773 ModestMsgEditWindowPrivate *priv;
3774 TnyHeader *header = NULL;
3776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3777 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3781 if (priv->draft_msg != NULL) {
3782 g_object_unref (priv->draft_msg);
3785 if (draft != NULL) {
3786 g_object_ref (draft);
3787 header = tny_msg_get_header (draft);
3788 if (priv->msg_uid) {
3789 g_free (priv->msg_uid);
3790 priv->msg_uid = NULL;
3792 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3795 priv->draft_msg = draft;
3799 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3800 GtkTextIter *start, GtkTextIter *end,
3803 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3804 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3807 if (tag == NULL) return;
3808 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3809 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3810 replace_with_images (window, priv->images);
3815 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3818 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3820 g_return_if_fail (TNY_IS_MIME_PART (part));
3821 tny_list_prepend (priv->attachments, (GObject *) part);
3822 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3823 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3824 gtk_widget_show_all (priv->attachments_caption);
3825 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3829 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3831 ModestMsgEditWindowPrivate *priv;
3833 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3834 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3836 return priv->msg_uid;
3840 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3841 ModestMsgEditWindowWidgetType widget_type)
3843 ModestMsgEditWindowPrivate *priv;
3845 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3846 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3848 switch (widget_type) {
3849 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3850 return priv->msg_body;
3852 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3853 return priv->to_field;
3855 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3856 return priv->cc_field;
3858 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3859 return priv->bcc_field;
3861 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3862 return priv->subject_field;
3864 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3865 return priv->attachments_view;
3873 remove_tags (WPTextBuffer *buffer)
3875 GtkTextIter start, end;
3877 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3878 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3880 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3884 on_account_removed (TnyAccountStore *account_store,
3885 TnyAccount *account,
3888 /* Do nothing if it's a store account, because we use the
3889 transport to send the messages */
3890 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3891 const gchar *parent_acc = NULL;
3892 const gchar *our_acc = NULL;
3894 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3895 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3896 /* Close this window if I'm showing a message of the removed account */
3897 if (strcmp (parent_acc, our_acc) == 0)
3898 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3902 static void update_signature (ModestMsgEditWindow *self,
3903 const gchar *old_account,
3904 const gchar *new_account)
3906 ModestMsgEditWindowPrivate *priv;
3907 gboolean has_old_signature, has_new_signature;
3909 GtkTextIter match_start, match_end;
3910 ModestAccountMgr *mgr;
3912 gchar *full_signature;
3914 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3916 gtk_text_buffer_begin_user_action (priv->text_buffer);
3918 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3919 mgr = modest_runtime_get_account_mgr ();
3923 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3924 if (has_old_signature) {
3925 full_signature = g_strconcat ("\n--\n", signature, NULL);
3926 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3927 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3929 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3930 &match_start, &match_end, NULL)) {
3933 g_free (full_signature);
3938 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3939 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3940 if (has_new_signature) {
3941 full_signature = g_strconcat ("\n--\n", signature, NULL);
3942 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3943 g_free (full_signature);
3946 gtk_text_buffer_end_user_action (priv->text_buffer);
3950 from_field_changed (HildonPickerButton *button,
3951 ModestMsgEditWindow *self)
3953 ModestMsgEditWindowPrivate *priv;
3954 gchar *old_account, *new_account;
3956 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3958 old_account = priv->last_from_account;
3959 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3960 new_account = priv->last_from_account;
3962 update_signature (self, old_account, new_account);
3966 typedef struct _MessageSettingsHelper {
3967 ModestMsgEditWindow *window;
3968 GSList *priority_group;
3969 GSList *format_group;
3970 GtkToggleButton *current_priority;
3971 GtkToggleButton *current_format;
3972 } MessageSettingsHelper;
3975 on_priority_toggle (GtkToggleButton *button,
3976 MessageSettingsHelper *helper)
3979 ModestMsgEditWindowPrivate *priv;
3981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3982 if (gtk_toggle_button_get_active (button)) {
3984 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3985 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3986 if ((node_button != button) &&
3987 gtk_toggle_button_get_active (node_button)) {
3988 gtk_toggle_button_set_active (node_button, FALSE);
3991 helper->current_priority = button;
3993 gboolean found = FALSE;
3994 /* If no one is active, activate it again */
3995 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3996 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3997 if (gtk_toggle_button_get_active (node_button)) {
4003 gtk_toggle_button_set_active (button, TRUE);
4009 on_format_toggle (GtkToggleButton *button,
4010 MessageSettingsHelper *helper)
4013 ModestMsgEditWindowPrivate *priv;
4015 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4016 if (gtk_toggle_button_get_active (button)) {
4018 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4019 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4020 if ((node_button != button) &&
4021 gtk_toggle_button_get_active (node_button)) {
4022 gtk_toggle_button_set_active (node_button, FALSE);
4025 helper->current_format = button;
4027 gboolean found = FALSE;
4028 /* If no one is active, activate it again */
4029 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4030 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4031 if (gtk_toggle_button_get_active (node_button)) {
4037 gtk_toggle_button_set_active (button, TRUE);
4044 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4049 GtkWidget *priority_hbox;
4050 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4051 GtkWidget *captioned;
4052 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4053 GtkWidget *format_hbox;
4054 GtkWidget *html_toggle, *text_toggle;
4055 ModestMsgEditWindowPrivate *priv;
4056 MessageSettingsHelper helper = {0,};
4058 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4059 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4060 helper.window = window;
4061 helper.priority_group = NULL;
4062 helper.format_group = NULL;
4064 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4065 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4067 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4068 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4069 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4070 vbox = gtk_vbox_new (FALSE, 0);
4071 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4072 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4073 gtk_container_add (GTK_CONTAINER (align), vbox);
4074 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4075 gtk_widget_show (align);
4076 gtk_widget_show (vbox);
4078 /* Priority toggles */
4079 priority_hbox = gtk_hbox_new (TRUE, 0);
4080 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4081 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4082 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4083 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4084 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4085 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4086 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4087 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4088 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4089 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4090 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4091 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4092 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4093 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4094 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4095 gtk_widget_show_all (priority_hbox);
4096 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4097 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4098 gtk_widget_show (captioned);
4099 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4101 /* format toggles */
4102 format_hbox = gtk_hbox_new (TRUE, 0);
4103 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4104 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4105 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4106 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4107 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4108 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4109 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4110 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4111 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4112 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4113 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4114 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4115 gtk_widget_show_all (format_hbox);
4116 gtk_widget_show (format_hbox);
4117 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4120 g_object_unref (title_sizegroup);
4121 g_object_unref (value_sizegroup);
4123 /* Set current values */
4124 switch (priv->priority_flags) {
4125 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4126 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4127 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4129 case TNY_HEADER_FLAG_LOW_PRIORITY:
4130 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4131 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4134 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4135 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4139 switch (modest_msg_edit_window_get_format (window)) {
4140 case MODEST_MSG_EDIT_FORMAT_TEXT:
4141 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4142 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4144 case MODEST_MSG_EDIT_FORMAT_HTML:
4146 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4147 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4151 /* Signal connects */
4152 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4153 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4154 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4155 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4156 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4158 /* Save settings if the user clicked on done */
4159 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4160 TnyHeaderFlags flags;
4161 ModestMsgEditFormat old_format, new_format;
4163 /* Set priority flags */
4164 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4165 if (priv->priority_flags != flags)
4166 modest_msg_edit_window_set_priority_flags (window, flags);
4168 /* Set edit format */
4169 old_format = modest_msg_edit_window_get_format (window);
4170 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4171 if (old_format != new_format) {
4172 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4173 modest_msg_edit_window_set_file_format (window, file_format);
4177 gtk_widget_destroy (dialog);
4178 g_slist_free (helper.priority_group);
4182 on_message_settings (GtkAction *action,
4183 ModestMsgEditWindow *window)
4185 modest_msg_edit_window_show_msg_settings_dialog (window);
4189 on_cc_button_toggled (HildonCheckButton *button,
4190 ModestMsgEditWindow *window)
4192 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4194 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4195 hildon_check_button_get_active (button));
4199 on_bcc_button_toggled (HildonCheckButton *button,
4200 ModestMsgEditWindow *window)
4202 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4204 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4205 hildon_check_button_get_active (button));
4209 setup_menu (ModestMsgEditWindow *self)
4211 ModestMsgEditWindowPrivate *priv = NULL;
4213 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4215 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4217 /* Settings menu buttons */
4218 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4219 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4221 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4222 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4223 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4225 priv->cc_button = hildon_check_button_new (0);
4226 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4227 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4229 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4231 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4232 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4233 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4234 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4236 priv->bcc_button = hildon_check_button_new (0);
4237 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4238 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4240 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4242 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4243 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4244 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4245 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4247 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4248 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4249 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4250 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: add attachment"), NULL,
4251 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4253 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4254 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4255 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4256 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4257 APP_MENU_CALLBACK (on_message_settings),
4259 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4260 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4265 emit_open_addressbook (GtkButton *button,
4266 ModestRecptEditor *editor)
4268 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4272 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4273 const gchar *label, GtkWidget *control)
4275 GtkWidget *abook_button;
4278 GtkWidget *label_widget;
4280 box = gtk_hbox_new (FALSE, 0);
4282 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4283 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4285 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4286 label_widget = gtk_label_new (label);
4287 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4288 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4290 gtk_container_add (GTK_CONTAINER (align), abook_button);
4291 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4292 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4293 if (title_size_group)
4294 gtk_size_group_add_widget (title_size_group, label_widget);
4295 if (value_size_group)
4296 gtk_size_group_add_widget (value_size_group, control);
4298 g_signal_connect (G_OBJECT (abook_button), "clicked",
4299 G_CALLBACK (emit_open_addressbook), control);