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 48
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 *add_attachment_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->add_attachment_button), "clicked",
742 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
743 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
744 G_CALLBACK (from_field_changed), obj);
746 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
747 G_CALLBACK (msg_body_focus), obj);
748 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
749 G_CALLBACK (msg_body_focus), obj);
750 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
751 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
752 "changed", G_CALLBACK (recpt_field_changed), obj);
753 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
754 "changed", G_CALLBACK (recpt_field_changed), obj);
755 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
756 "changed", G_CALLBACK (recpt_field_changed), obj);
757 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
758 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
759 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
761 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
762 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
764 priv->clipboard_change_handler_id =
765 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
766 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
767 priv->default_clipboard_change_handler_id =
768 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
769 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
771 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
772 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
773 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
777 init_wp_text_view_style ()
779 static gboolean initialized = FALSE;
782 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
788 init_window (ModestMsgEditWindow *obj)
790 GtkWidget *to_caption, *subject_caption;
791 GtkWidget *main_vbox;
792 GtkWidget *add_attachment_align;
793 ModestMsgEditWindowPrivate *priv;
794 GtkActionGroup *action_group;
795 ModestWindowPrivate *parent_priv;
796 GdkPixbuf *window_icon = NULL;
797 GError *error = NULL;
799 GtkSizeGroup *title_size_group;
800 GtkSizeGroup *value_size_group;
801 GtkWidget *attachment_icon;
802 GtkWidget *window_box;
803 GtkWidget *window_align;
804 #if (GTK_MINOR_VERSION >= 10)
805 GdkAtom deserialize_type;
808 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
809 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
811 parent_priv->ui_manager = gtk_ui_manager_new();
812 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
813 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
815 /* Add common actions */
816 gtk_action_group_add_actions (action_group,
817 modest_msg_edit_action_entries,
818 G_N_ELEMENTS (modest_msg_edit_action_entries),
820 gtk_action_group_add_actions (action_group,
821 hildon2_msg_edit_action_entries,
822 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
824 gtk_action_group_add_toggle_actions (action_group,
825 modest_msg_edit_toggle_action_entries,
826 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
828 gtk_action_group_add_radio_actions (action_group,
829 modest_msg_edit_alignment_radio_action_entries,
830 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
832 G_CALLBACK (modest_ui_actions_on_change_justify),
834 gtk_action_group_add_radio_actions (action_group,
835 modest_msg_edit_priority_action_entries,
836 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
838 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
840 gtk_action_group_add_radio_actions (action_group,
841 modest_msg_edit_file_format_action_entries,
842 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
843 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
844 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
846 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
847 g_object_unref (action_group);
849 /* Load the UI definition */
850 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
853 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
854 g_clear_error (&error);
857 /* Add accelerators */
858 gtk_window_add_accel_group (GTK_WINDOW (obj),
859 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
861 parent_priv->menubar = NULL;
863 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
864 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
866 /* Note: This ModestPairList* must exist for as long as the picker
867 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
868 * so it can't know how to manage its memory. */
869 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
870 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
872 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
873 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
874 _("mail_va_from"), priv->from_field);
875 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.5, 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 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
881 priv->priority_icon = gtk_image_new ();
882 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
883 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
884 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
885 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
886 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
887 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
888 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
889 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
890 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
891 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
892 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
893 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
894 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
895 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
896 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
897 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
898 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
899 priv->attachments_view = modest_attachments_view_new (NULL);
900 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
901 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
903 priv->header_box = gtk_vbox_new (FALSE, 0);
905 to_caption = _create_addressbook_box
906 (title_size_group, value_size_group,
907 _("mail_va_to"), priv->to_field);
908 priv->cc_caption = _create_addressbook_box
909 (title_size_group, value_size_group,
910 _("mail_va_cc"), priv->cc_field);
911 priv->bcc_caption = _create_addressbook_box
912 (title_size_group, value_size_group,
913 _("mail_va_hotfix1"), priv->bcc_field);
914 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
915 _("mail_va_subject"), FALSE, priv->subject_box);
916 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
917 _("mail_va_attachment"),
919 priv->attachments_view,
920 HILDON_SIZE_AUTO_WIDTH |
921 HILDON_SIZE_AUTO_HEIGHT);
922 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
923 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
924 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
925 g_object_unref (title_size_group);
926 g_object_unref (value_size_group);
928 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
929 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
930 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
931 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
932 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
933 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
934 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
936 init_wp_text_view_style ();
938 priv->msg_body = modest_wp_text_view_new ();
941 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
942 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
943 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
944 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
945 #if (GTK_MINOR_VERSION >= 10)
946 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
947 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
949 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
950 deserialize_type, TRUE);
952 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
954 priv->find_toolbar = hildon_find_toolbar_new (NULL);
955 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
957 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
959 priv->pannable = hildon_pannable_area_new ();
961 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
963 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
964 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
965 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
967 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
968 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
969 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
971 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
972 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
974 window_box = gtk_vbox_new (FALSE, 0);
975 gtk_container_add (GTK_CONTAINER(obj), window_box);
977 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
979 /* Set window icon */
980 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
982 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
983 g_object_unref (window_icon);
988 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
990 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
992 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
993 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
994 priv->clipboard_change_handler_id))
995 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
996 priv->clipboard_change_handler_id);
997 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
998 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
999 priv->default_clipboard_change_handler_id))
1000 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1001 priv->default_clipboard_change_handler_id);
1003 if (priv->account_removed_handler_id &&
1004 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1005 priv->account_removed_handler_id))
1006 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1007 priv->account_removed_handler_id);
1011 modest_msg_edit_window_finalize (GObject *obj)
1013 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1015 /* Sanity check: shouldn't be needed, the window mgr should
1016 call this function before */
1017 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1019 if (priv->font_dialog != NULL) {
1020 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1023 if (priv->clipboard_text != NULL) {
1024 g_free (priv->clipboard_text);
1025 priv->clipboard_text = NULL;
1028 if (priv->draft_msg != NULL) {
1029 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1030 if (TNY_IS_HEADER (header)) {
1031 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1032 modest_window_mgr_unregister_header (mgr, header);
1034 g_object_unref (priv->draft_msg);
1035 priv->draft_msg = NULL;
1037 if (priv->outbox_msg != NULL) {
1038 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1039 if (TNY_IS_HEADER (header)) {
1040 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1041 modest_window_mgr_unregister_header (mgr, header);
1043 g_object_unref (priv->outbox_msg);
1044 priv->outbox_msg = NULL;
1046 if (priv->correct_scroll_idle > 0) {
1047 g_source_remove (priv->correct_scroll_idle);
1048 priv->correct_scroll_idle = 0;
1050 if (priv->scroll_drag_timeout_id > 0) {
1051 g_source_remove (priv->scroll_drag_timeout_id);
1052 priv->scroll_drag_timeout_id = 0;
1054 if (priv->clipboard_owner_idle > 0) {
1055 g_source_remove (priv->clipboard_owner_idle);
1056 priv->clipboard_owner_idle = 0;
1058 if (priv->original_account_name)
1059 g_free (priv->original_account_name);
1060 if (priv->original_mailbox)
1061 g_free (priv->original_mailbox);
1062 g_free (priv->msg_uid);
1063 g_free (priv->last_search);
1064 g_free (priv->references);
1065 g_free (priv->in_reply_to);
1066 g_object_unref (priv->faces_model);
1067 g_object_unref (priv->sizes_model);
1068 g_object_unref (priv->attachments);
1069 g_object_unref (priv->images);
1071 /* This had to stay alive for as long as the picker that used it: */
1072 modest_pair_list_free (priv->from_field_protos);
1074 G_OBJECT_CLASS(parent_class)->finalize (obj);
1078 pixbuf_size_prepared (GdkPixbufLoader *loader,
1081 ModestMsgEditWindow *self)
1083 gint new_height, new_width;
1086 new_height = height;
1090 if (width > IMAGE_MAX_WIDTH) {
1091 new_height = height * IMAGE_MAX_WIDTH / width;
1092 new_width = IMAGE_MAX_WIDTH;
1095 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1099 pixbuf_from_stream (TnyStream *stream,
1100 const gchar *mime_type,
1101 guint64 *stream_size,
1102 ModestMsgEditWindow *self)
1104 GdkPixbufLoader *loader;
1107 GError *error = NULL;
1111 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1113 if (loader == NULL) {
1118 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1120 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1122 tny_stream_reset (TNY_STREAM (stream));
1123 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1124 unsigned char read_buffer[128];
1126 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1128 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1131 /* Allow some UI responsiveness */
1132 while (gtk_events_pending ())
1133 gtk_main_iteration ();
1135 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1137 gdk_pixbuf_loader_close (loader, &error);
1140 g_error_free (error);
1141 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1143 g_object_ref (pixbuf);
1144 g_object_unref (loader);
1149 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1150 GdkPixbuf *new_pixbuf;
1152 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1153 gdk_pixbuf_get_width (pixbuf);
1154 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1155 g_object_unref (pixbuf);
1156 pixbuf = new_pixbuf;
1160 *stream_size = size;
1166 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1168 ModestMsgEditWindowPrivate *priv;
1171 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1173 g_object_ref (self);
1174 for (iter = tny_list_create_iterator (attachments);
1175 !tny_iterator_is_done (iter);
1176 tny_iterator_next (iter)) {
1177 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1178 const gchar *cid = tny_mime_part_get_content_id (part);
1179 const gchar *mime_type = tny_mime_part_get_content_type (part);
1180 if ((cid != NULL)&&(mime_type != NULL)) {
1181 guint64 stream_size;
1182 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1183 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1186 g_object_unref (stream);
1188 if (pixbuf != NULL) {
1189 priv->images_count ++;
1190 priv->images_size += stream_size;
1191 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1192 g_object_unref (pixbuf);
1195 g_object_unref (part);
1197 g_object_unref (iter);
1198 g_object_unref (self);
1202 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1204 TnyMimePart *parent = NULL;
1205 const gchar *content_type = NULL;
1206 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1208 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1210 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1211 parent = g_object_ref (msg);
1212 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1213 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1216 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1217 iter = tny_list_create_iterator (parts);
1218 while (!tny_iterator_is_done (iter)) {
1220 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1221 content_type = tny_mime_part_get_content_type (part);
1222 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1226 g_object_unref (part);
1228 tny_iterator_next (iter);
1230 g_object_unref (iter);
1231 g_object_unref (parts);
1234 if (parent != NULL) {
1235 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1238 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1239 iter = tny_list_create_iterator (parts);
1240 while (!tny_iterator_is_done (iter)) {
1242 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1243 content_type = tny_mime_part_get_content_type (part);
1244 if (content_type && g_str_has_prefix (content_type, "image/")) {
1245 tny_list_prepend (priv->images, (GObject *) part);
1247 g_object_unref (part);
1248 tny_iterator_next (iter);
1250 g_object_unref (iter);
1251 g_object_unref (parts);
1252 g_object_unref (parent);
1257 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1260 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1262 for (iter = tny_list_create_iterator (attachments) ;
1263 !tny_iterator_is_done (iter);
1264 tny_iterator_next (iter)) {
1265 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1266 const gchar *cid = tny_mime_part_get_content_id (part);
1268 char *invalid = NULL;
1269 gint int_cid = strtol (cid, &invalid, 10);
1270 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1271 priv->next_cid = int_cid + 1;
1274 g_object_unref (part);
1276 g_object_unref (iter);
1280 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1283 gchar *to, *cc, *bcc, *subject;
1285 ModestMsgEditWindowPrivate *priv;
1286 ModestWindowPrivate *parent_priv;
1288 TnyHeaderFlags priority_flags;
1289 TnyFolder *msg_folder;
1290 gboolean is_html = FALSE;
1291 gboolean field_view_set;
1293 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1294 g_return_if_fail (TNY_IS_MSG (msg));
1296 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1297 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1299 header = tny_msg_get_header (msg);
1300 to = tny_header_dup_to (header);
1301 cc = tny_header_dup_cc (header);
1302 bcc = tny_header_dup_bcc (header);
1303 subject = tny_header_dup_subject (header);
1305 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1306 priority_flags = tny_header_get_priority (header);
1309 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1311 field_view_set = TRUE;
1313 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1314 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1315 gtk_widget_show (priv->cc_caption);
1316 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1317 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1318 gtk_widget_hide (priv->cc_caption);
1319 field_view_set = FALSE;
1321 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1323 field_view_set = TRUE;
1325 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1326 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1327 gtk_widget_show (priv->bcc_caption);
1328 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1329 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1330 gtk_widget_hide (priv->bcc_caption);
1331 field_view_set = FALSE;
1333 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1337 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1338 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1341 update_window_title (self);
1343 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1344 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1346 if ((body == NULL)||(body[0] == '\0')) {
1348 body = modest_text_utils_convert_to_html ("");
1351 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1352 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1355 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1358 /* Add attachments to the view */
1359 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1360 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1361 if (tny_list_get_length (priv->attachments) == 0) {
1362 gtk_widget_hide (priv->attachments_caption);
1364 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1365 gtk_widget_show_all (priv->attachments_caption);
1367 get_related_images (self, msg);
1368 update_next_cid (self, priv->attachments);
1369 update_next_cid (self, priv->images);
1370 replace_with_images (self, priv->images);
1372 if (preserve_is_rich && !is_html) {
1373 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1374 /* Get the default format required from configuration */
1375 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1376 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1379 /* Set the default focus depending on having already a To: field or not */
1380 if ((!to)||(*to == '\0')) {
1381 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1383 gtk_widget_grab_focus (priv->msg_body);
1386 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1388 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1389 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1391 modest_msg_edit_window_set_modified (self, FALSE);
1393 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1394 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1395 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1396 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1398 if (priv->msg_uid) {
1399 g_free (priv->msg_uid);
1400 priv->msg_uid = NULL;
1403 /* we should set a reference to the incoming message if it is a draft */
1404 msg_folder = tny_msg_get_folder (msg);
1406 if (modest_tny_folder_is_local_folder (msg_folder)) {
1407 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1408 if (type == TNY_FOLDER_TYPE_INVALID)
1409 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1411 if (type == TNY_FOLDER_TYPE_DRAFTS)
1412 priv->draft_msg = g_object_ref(msg);
1413 if (type == TNY_FOLDER_TYPE_OUTBOX)
1414 priv->outbox_msg = g_object_ref(msg);
1415 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1417 g_object_unref (msg_folder);
1428 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1430 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1431 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1432 GtkWidget *placeholder;
1433 GtkWidget *tool_item;
1438 GtkWidget *sizes_menu;
1439 GtkWidget *fonts_menu;
1445 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1446 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1447 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1448 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1450 /* Font color placeholder */
1451 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1452 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1455 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1456 priv->font_color_button = hildon_color_button_new ();
1457 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1458 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1459 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1460 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1461 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1462 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1463 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1464 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1466 G_CALLBACK (modest_msg_edit_window_color_button_change),
1469 /* Font size and face placeholder */
1470 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1471 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1473 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1474 priv->size_tool_button_label = gtk_label_new (NULL);
1475 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1476 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1477 size_text, "</span>", NULL);
1478 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1479 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1481 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1482 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1483 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1484 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1485 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1486 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1487 gtk_widget_set_sensitive (arrow, FALSE);
1488 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1489 sizes_menu = gtk_menu_new ();
1490 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1491 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1494 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1495 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1497 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1501 if (wp_font_size[size_index] == 12)
1502 priv->current_size_index = size_index;
1506 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1507 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1508 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1509 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1510 priv->font_size_toolitem = tool_item;
1513 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1514 priv->font_tool_button_label = gtk_label_new (NULL);
1515 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1516 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1517 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1519 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1520 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1521 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1522 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1523 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1524 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1525 gtk_widget_set_sensitive (arrow, FALSE);
1526 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1527 fonts_menu = gtk_menu_new ();
1528 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1529 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1532 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1534 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1535 0, wp_get_font_name (font_index),
1538 if (font_index == DEFAULT_FONT)
1539 priv->current_face_index = font_index;
1541 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1542 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1543 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1544 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1545 priv->font_face_toolitem = tool_item;
1547 /* Set expand and homogeneous for remaining items */
1548 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1549 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1550 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1551 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1552 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1553 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1554 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1555 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1556 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1558 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1559 will not show the tool items added to the placeholders) */
1560 gtk_widget_show_all (parent_priv->toolbar);
1562 /* Set the no show all *after* showing all items. We do not
1563 want the toolbar to be shown with a show all because it
1564 could go agains the gconf setting regarding showing or not
1565 the toolbar of the editor window */
1566 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1572 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1575 ModestWindowPrivate *parent_priv;
1576 ModestMsgEditWindowPrivate *priv;
1577 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1578 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1579 ModestWindowMgr *mgr = NULL;
1581 g_return_val_if_fail (msg, NULL);
1582 g_return_val_if_fail (account_name, NULL);
1584 mgr = modest_runtime_get_window_mgr ();
1586 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1588 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1589 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1591 /* Menubar. Update the state of some toggles */
1592 priv->from_field_protos = get_transports ();
1593 priv->original_mailbox = NULL;
1594 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1595 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1596 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1597 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1598 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1599 priv->original_mailbox = g_strdup (mailbox);
1600 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1601 /* We set the first mailbox as the active mailbox */
1602 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1603 if (priv->original_mailbox != NULL)
1604 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1605 (gpointer) priv->original_mailbox);
1607 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1608 (gpointer) account_name);
1610 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1612 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1613 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1615 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1616 hildon_touch_selector_get_current_text
1617 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1618 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1619 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1622 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1624 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1626 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1627 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1629 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1631 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1632 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1633 /* Add common dimming rules */
1634 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1635 modest_msg_edit_window_toolbar_dimming_entries,
1636 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1637 MODEST_WINDOW (obj));
1638 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1639 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1640 MODEST_WINDOW (obj));
1641 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1642 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1643 MODEST_WINDOW (obj));
1644 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1645 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1646 MODEST_WINDOW (obj));
1647 /* Insert dimming rules group for this window */
1648 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1649 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1651 /* Setup app menu */
1652 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1654 /* Checks the dimming rules */
1655 g_object_unref (toolbar_rules_group);
1656 g_object_unref (clipboard_rules_group);
1657 gtk_widget_hide (priv->priority_icon);
1658 gtk_widget_queue_resize (priv->subject_box);
1659 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1661 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1663 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1664 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1665 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1666 priv->update_caption_visibility = TRUE;
1668 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1670 /* Track account-removed signal, this window should be closed
1671 in the case we're creating a mail associated to the account
1673 priv->account_removed_handler_id =
1674 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1676 G_CALLBACK(on_account_removed),
1679 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1681 return (ModestWindow*) obj;
1685 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1687 GString **string_buffer = (GString **) user_data;
1689 *string_buffer = g_string_append (*string_buffer, buffer);
1695 * @result: A new string which should be freed with g_free().
1698 get_formatted_data (ModestMsgEditWindow *edit_window)
1700 ModestMsgEditWindowPrivate *priv;
1701 GString *string_buffer = g_string_new ("");
1703 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1705 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1707 modest_text_utils_hyperlinkify (string_buffer);
1709 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1711 return g_string_free (string_buffer, FALSE);
1716 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1719 const gchar *account_name;
1720 ModestMsgEditWindowPrivate *priv;
1721 TnyIterator *att_iter;
1722 const gchar *picker_active_id;
1724 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1726 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1728 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1729 g_return_val_if_fail (picker_active_id, NULL);
1730 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1732 /* don't free these (except from) */
1733 data = g_slice_new0 (MsgData);
1734 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1735 data->account_name = g_strdup (account_name);
1736 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1737 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1738 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1739 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1740 data->references = g_strdup (priv->references);
1741 data->in_reply_to = g_strdup (priv->in_reply_to);
1742 if (priv->draft_msg) {
1743 data->draft_msg = g_object_ref (priv->draft_msg);
1744 } else if (priv->outbox_msg) {
1745 data->draft_msg = g_object_ref (priv->outbox_msg);
1747 data->draft_msg = NULL;
1750 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1752 gtk_text_buffer_get_bounds (buf, &b, &e);
1753 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1755 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1756 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1758 data->html_body = NULL;
1760 /* deep-copy the data */
1761 att_iter = tny_list_create_iterator (priv->attachments);
1762 data->attachments = NULL;
1763 while (!tny_iterator_is_done (att_iter)) {
1764 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1765 if (!(TNY_IS_MIME_PART(part))) {
1766 g_warning ("strange data in attachment list");
1767 g_object_unref (part);
1768 tny_iterator_next (att_iter);
1771 data->attachments = g_list_append (data->attachments,
1773 tny_iterator_next (att_iter);
1775 g_object_unref (att_iter);
1777 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1778 att_iter = tny_list_create_iterator (priv->images);
1779 data->images = NULL;
1780 while (!tny_iterator_is_done (att_iter)) {
1781 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1783 if (!(TNY_IS_MIME_PART(part))) {
1784 g_warning ("strange data in attachment list");
1785 g_object_unref (part);
1786 tny_iterator_next (att_iter);
1789 cid = tny_mime_part_get_content_id (part);
1791 gchar *image_tag_id;
1792 GtkTextTag *image_tag;
1794 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1795 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1796 g_free (image_tag_id);
1798 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1800 ((gtk_text_iter_has_tag (&iter, image_tag))||
1801 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1802 data->images = g_list_append (data->images,
1803 g_object_ref (part));
1805 g_object_unref (part);
1806 tny_iterator_next (att_iter);
1808 g_object_unref (att_iter);
1810 data->priority_flags = priv->priority_flags;
1817 unref_gobject (GObject *obj, gpointer data)
1819 if (!G_IS_OBJECT(obj))
1821 g_object_unref (obj);
1825 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1828 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1836 g_free (data->from);
1837 g_free (data->subject);
1838 g_free (data->plain_body);
1839 g_free (data->html_body);
1840 g_free (data->account_name);
1841 g_free (data->references);
1842 g_free (data->in_reply_to);
1844 if (data->draft_msg != NULL) {
1845 g_object_unref (data->draft_msg);
1846 data->draft_msg = NULL;
1849 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1850 g_list_free (data->attachments);
1851 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1852 g_list_free (data->images);
1854 g_slice_free (MsgData, data);
1858 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1860 guint64 *parts_size)
1862 ModestMsgEditWindowPrivate *priv;
1864 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1866 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1868 /* TODO: add images */
1869 *parts_size += priv->images_size;
1870 *parts_count += priv->images_count;
1875 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1878 ModestMsgEditWindowPrivate *priv = NULL;
1879 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1883 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1885 return MODEST_MSG_EDIT_FORMAT_HTML;
1887 return MODEST_MSG_EDIT_FORMAT_TEXT;
1891 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1892 ModestMsgEditFormat format)
1894 ModestMsgEditWindowPrivate *priv;
1896 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1897 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1900 case MODEST_MSG_EDIT_FORMAT_HTML:
1901 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1903 case MODEST_MSG_EDIT_FORMAT_TEXT:
1904 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1907 g_return_if_reached ();
1911 ModestMsgEditFormatState *
1912 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1914 ModestMsgEditFormatState *format_state = NULL;
1915 ModestMsgEditWindowPrivate *priv;
1916 WPTextBufferFormat *buffer_format;
1918 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1920 buffer_format = g_new0 (WPTextBufferFormat, 1);
1921 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1923 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1925 format_state = g_new0 (ModestMsgEditFormatState, 1);
1926 format_state->bold = buffer_format->bold&0x1;
1927 format_state->italics = buffer_format->italic&0x1;
1928 format_state->bullet = buffer_format->bullet&0x1;
1929 format_state->color = buffer_format->color;
1930 format_state->font_size = buffer_format->font_size;
1931 format_state->font_family = wp_get_font_name (buffer_format->font);
1932 format_state->justification = buffer_format->justification;
1933 g_free (buffer_format);
1935 return format_state;
1940 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1941 const ModestMsgEditFormatState *format_state)
1943 ModestMsgEditWindowPrivate *priv;
1944 WPTextBufferFormat *buffer_format;
1945 WPTextBufferFormat *current_format;
1947 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1948 g_return_if_fail (format_state != NULL);
1950 buffer_format = g_new0 (WPTextBufferFormat, 1);
1951 current_format = g_new0 (WPTextBufferFormat, 1);
1953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1954 gtk_widget_grab_focus (priv->msg_body);
1955 buffer_format->bold = (format_state->bold != FALSE);
1956 buffer_format->italic = (format_state->italics != FALSE);
1957 buffer_format->color = format_state->color;
1958 buffer_format->font_size = format_state->font_size;
1959 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1960 buffer_format->justification = format_state->justification;
1961 buffer_format->bullet = format_state->bullet;
1963 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1965 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1966 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1967 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1968 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1969 buffer_format->cs.font = (buffer_format->font != current_format->font);
1970 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1971 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1973 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1974 if (buffer_format->cs.bold) {
1975 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1976 GINT_TO_POINTER (buffer_format->bold&0x1));
1978 if (buffer_format->cs.italic) {
1979 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1980 GINT_TO_POINTER (buffer_format->italic&0x1));
1982 if (buffer_format->cs.color) {
1983 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1984 GINT_TO_POINTER (&(buffer_format->color)));
1986 if (buffer_format->cs.font_size) {
1987 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1988 GINT_TO_POINTER (buffer_format->font_size));
1990 if (buffer_format->cs.justification) {
1991 switch (buffer_format->justification) {
1992 case GTK_JUSTIFY_LEFT:
1993 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1994 GINT_TO_POINTER(TRUE));
1996 case GTK_JUSTIFY_CENTER:
1997 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1998 GINT_TO_POINTER(TRUE));
2000 case GTK_JUSTIFY_RIGHT:
2001 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2002 GINT_TO_POINTER(TRUE));
2009 if (buffer_format->cs.font) {
2010 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2011 GINT_TO_POINTER (buffer_format->font));
2013 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2014 if (buffer_format->cs.bullet) {
2015 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2016 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2018 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2020 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2022 g_free (buffer_format);
2023 g_free (current_format);
2025 /* Check dimming rules */
2026 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2027 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2031 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2033 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2035 ModestWindowPrivate *parent_priv;
2036 ModestMsgEditWindowPrivate *priv;
2038 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2039 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2041 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2042 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2043 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2044 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2046 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2047 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2048 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2051 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2053 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2054 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2056 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2057 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2059 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2060 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2063 switch (buffer_format->justification)
2065 case GTK_JUSTIFY_LEFT:
2066 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2068 case GTK_JUSTIFY_CENTER:
2069 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2071 case GTK_JUSTIFY_RIGHT:
2072 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2079 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2081 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2082 G_CALLBACK (modest_msg_edit_window_color_button_change),
2084 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2085 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2086 G_CALLBACK (modest_msg_edit_window_color_button_change),
2089 if (priv->current_size_index != buffer_format->font_size) {
2093 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2094 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2098 priv->current_size_index = buffer_format->font_size;
2100 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2101 markup = g_strconcat ("<span font_family='Sans'>",
2102 size_text, "</span>", NULL);
2104 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2108 gtk_tree_path_free (path);
2111 if (priv->current_face_index != buffer_format->font) {
2115 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2116 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2120 priv->current_face_index = buffer_format->font;
2121 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2122 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2123 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2130 g_free (buffer_format);
2134 #ifdef MODEST_HILDON_VERSION_0
2136 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2139 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2140 ModestMsgEditWindowPrivate *priv;
2141 GtkWidget *dialog = NULL;
2143 GdkColor *new_color = NULL;
2145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2146 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2148 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2149 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2150 g_free (buffer_format);
2152 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2153 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2154 if (new_color != NULL) {
2155 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2156 (gpointer) new_color);
2159 gtk_widget_destroy (dialog);
2164 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2167 ModestMsgEditWindowPrivate *priv;
2168 GtkWidget *dialog = NULL;
2170 GdkColor *old_color = NULL;
2171 const GdkColor *new_color = NULL;
2173 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2174 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2176 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2177 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2179 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2180 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2181 if (new_color != NULL)
2182 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2184 gtk_widget_destroy (dialog);
2190 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2193 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2194 ModestMsgEditWindowPrivate *priv;
2195 GtkWidget *dialog = NULL;
2197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2198 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2200 dialog = hildon_color_chooser_new ();
2201 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2202 g_free (buffer_format);
2204 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2206 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2207 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2210 gtk_widget_destroy (dialog);
2215 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2218 ModestMsgEditWindowPrivate *priv;
2219 GtkWidget *dialog = NULL;
2220 GdkColor *old_color = NULL;
2222 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2223 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2225 dialog = hildon_color_chooser_new ();
2226 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2228 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2230 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2231 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2233 gtk_widget_destroy (dialog);
2236 #endif /*!MODEST_HILDON_VERSION_0*/
2241 create_stream_for_uri (const gchar* uri)
2246 TnyStream *result = NULL;
2248 GnomeVFSHandle *handle = NULL;
2249 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2250 if (test == GNOME_VFS_OK) {
2251 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2252 /* Streams over OBEX (Bluetooth) are not seekable but
2253 * we expect them to be (we might need to read them
2254 * several times). So if this is a Bluetooth URI just
2255 * read the whole file into memory (this is not a fast
2256 * protocol so we can assume that these files are not
2257 * going to be very big) */
2258 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2259 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2260 TnyStream *memstream = tny_camel_mem_stream_new ();
2261 tny_stream_write_to_stream (vfssstream, memstream);
2262 g_object_unref (vfssstream);
2265 result = vfssstream;
2273 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2276 ModestMsgEditWindowPrivate *priv;
2277 GtkWidget *dialog = NULL;
2279 GSList *uris = NULL;
2280 GSList *uri_node = NULL;
2282 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2284 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2285 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2286 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2288 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2290 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2291 GTK_WINDOW (dialog), GTK_WINDOW (window));
2293 response = gtk_dialog_run (GTK_DIALOG (dialog));
2295 case GTK_RESPONSE_OK:
2297 gchar *current_folder;
2298 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2299 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2300 if (current_folder && current_folder != '\0') {
2302 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2303 current_folder, &err);
2305 g_debug ("Error storing latest used folder: %s", err->message);
2309 g_free (current_folder);
2315 gtk_widget_destroy (dialog);
2317 g_object_ref (window);
2318 /* The operation could take some time so allow the dialog to be closed */
2319 while (gtk_events_pending ())
2320 gtk_main_iteration ();
2322 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2324 GnomeVFSHandle *handle = NULL;
2325 GnomeVFSResult result;
2326 GtkTextIter position;
2327 GtkTextMark *insert_mark;
2329 uri = (const gchar *) uri_node->data;
2330 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2331 if (result == GNOME_VFS_OK) {
2333 GnomeVFSFileInfo *info;
2334 gchar *filename, *basename, *escaped_filename;
2335 TnyMimePart *mime_part;
2337 const gchar *mime_type = NULL;
2338 GnomeVFSURI *vfs_uri;
2339 guint64 stream_size;
2341 gnome_vfs_close (handle);
2342 vfs_uri = gnome_vfs_uri_new (uri);
2344 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2345 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2346 g_free (escaped_filename);
2347 gnome_vfs_uri_unref (vfs_uri);
2348 info = gnome_vfs_file_info_new ();
2350 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2351 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2353 mime_type = gnome_vfs_file_info_get_mime_type (info);
2355 mime_part = tny_platform_factory_new_mime_part
2356 (modest_runtime_get_platform_factory ());
2358 TnyStream *stream = create_stream_for_uri (uri);
2360 if (stream == NULL) {
2362 modest_platform_information_banner (NULL, NULL,
2363 _FM("sfil_ib_opening_not_allowed"));
2365 g_object_unref (mime_part);
2366 gnome_vfs_file_info_unref (info);
2370 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2372 content_id = g_strdup_printf ("%d", priv->next_cid);
2373 tny_mime_part_set_content_id (mime_part, content_id);
2374 g_free (content_id);
2377 basename = g_path_get_basename (filename);
2378 tny_mime_part_set_filename (mime_part, basename);
2381 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2383 if (pixbuf != NULL) {
2384 priv->images_size += stream_size;
2385 priv->images_count ++;
2386 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2387 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2388 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2389 tny_mime_part_get_content_id (mime_part), pixbuf);
2390 g_object_unref (pixbuf);
2392 tny_list_prepend (priv->images, (GObject *) mime_part);
2393 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2395 modest_platform_information_banner (NULL, NULL,
2396 _("mail_ib_file_operation_failed"));
2400 g_object_unref (mime_part);
2401 gnome_vfs_file_info_unref (info);
2405 g_object_unref (window);
2409 on_attach_file_response (GtkDialog *dialog,
2413 GSList *uris = NULL;
2415 GnomeVFSFileSize total_size, allowed_size;
2416 ModestMsgEditWindow *window;
2417 ModestMsgEditWindowPrivate *priv;
2422 case GTK_RESPONSE_OK:
2424 gchar *current_folder;
2426 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2427 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2428 if (current_folder && current_folder != '\0') {
2430 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2431 current_folder, &err);
2433 g_debug ("Error storing latest used folder: %s", err->message);
2437 g_free (current_folder);
2444 window = MODEST_MSG_EDIT_WINDOW (user_data);
2445 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2447 /* allowed size is the maximum size - what's already there */
2448 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2449 &att_num, &att_size);
2450 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2453 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2455 const gchar *uri = (const gchar *) uri_node->data;
2458 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2460 if (total_size > allowed_size) {
2461 g_warning ("%s: total size: %u",
2462 __FUNCTION__, (unsigned int)total_size);
2465 allowed_size -= total_size;
2467 g_slist_foreach (uris, (GFunc) g_free, NULL);
2468 g_slist_free (uris);
2470 gtk_widget_destroy (GTK_WIDGET (dialog));
2474 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2476 GtkWidget *dialog = NULL;
2477 ModestMsgEditWindowPrivate *priv;
2480 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2484 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2487 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2488 GTK_FILE_CHOOSER_ACTION_OPEN);
2489 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2490 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2491 if (conf_folder && conf_folder[0] != '\0') {
2492 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2495 /* Set the default folder to images folder */
2496 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2497 ".documents", NULL);
2498 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2499 g_free (docs_folder);
2501 g_free (conf_folder);
2502 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2503 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2504 GTK_WINDOW (dialog), GTK_WINDOW (window));
2506 /* Connect to response & show */
2507 g_signal_connect (dialog, "response",
2508 G_CALLBACK (on_attach_file_response), window);
2509 gtk_widget_show (dialog);
2514 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2516 GnomeVFSFileSize allowed_size)
2519 GnomeVFSHandle *handle = NULL;
2520 ModestMsgEditWindowPrivate *priv;
2521 GnomeVFSResult result;
2522 GnomeVFSFileSize size = 0;
2523 g_return_val_if_fail (window, 0);
2524 g_return_val_if_fail (uri, 0);
2526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2528 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2529 if (result == GNOME_VFS_OK) {
2530 TnyMimePart *mime_part;
2532 const gchar *mime_type = NULL;
2534 gchar *escaped_filename;
2537 GnomeVFSFileInfo *info;
2538 GnomeVFSURI *vfs_uri;
2540 gnome_vfs_close (handle);
2541 vfs_uri = gnome_vfs_uri_new (uri);
2544 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2545 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2546 g_free (escaped_filename);
2547 gnome_vfs_uri_unref (vfs_uri);
2549 info = gnome_vfs_file_info_new ();
2551 if (gnome_vfs_get_file_info (uri,
2553 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2555 mime_type = gnome_vfs_file_info_get_mime_type (info);
2556 mime_part = tny_platform_factory_new_mime_part
2557 (modest_runtime_get_platform_factory ());
2559 /* try to get the attachment's size; this may fail for weird
2560 * file systems, like obex, upnp... */
2561 if (allowed_size != 0 &&
2562 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2564 if (size > allowed_size) {
2565 modest_platform_information_banner (NULL, NULL,
2566 _FM("sfil_ib_opening_not_allowed"));
2571 g_warning ("%s: could not get attachment size", __FUNCTION__);
2573 stream = create_stream_for_uri (uri);
2575 if (stream == NULL) {
2577 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2579 g_object_unref (mime_part);
2581 gnome_vfs_file_info_unref (info);
2585 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2586 g_object_unref (stream);
2588 content_id = g_strdup_printf ("%d", priv->next_cid);
2589 tny_mime_part_set_content_id (mime_part, content_id);
2590 g_free (content_id);
2593 basename = g_path_get_basename (filename);
2594 tny_mime_part_set_filename (mime_part, basename);
2597 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2598 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2600 info->size == 0, info->size);
2601 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2602 gtk_widget_show_all (priv->attachments_caption);
2603 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2605 g_object_unref (mime_part);
2606 gnome_vfs_file_info_unref (info);
2613 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2616 ModestMsgEditWindowPrivate *priv;
2619 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2620 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2622 if (att_list == NULL) {
2623 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2624 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2625 g_object_unref (att_list);
2630 g_object_ref (att_list);
2633 if (tny_list_get_length (att_list) == 0) {
2634 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2636 gboolean dialog_response;
2637 gchar *message = NULL;
2638 gchar *filename = NULL;
2640 if (tny_list_get_length (att_list) == 1) {
2642 iter = tny_list_create_iterator (att_list);
2643 part = (TnyMimePart *) tny_iterator_get_current (iter);
2644 g_object_unref (iter);
2645 if (TNY_IS_MSG (part)) {
2646 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2648 filename = tny_header_dup_subject (header);
2649 g_object_unref (header);
2651 if (filename == NULL) {
2652 filename = g_strdup (_("mail_va_no_subject"));
2655 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2657 g_object_unref (part);
2659 filename = g_strdup ("");
2661 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2662 "emev_nc_delete_attachments",
2663 tny_list_get_length (att_list)), filename);
2666 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2670 if (dialog_response != GTK_RESPONSE_OK) {
2671 g_object_unref (att_list);
2675 for (iter = tny_list_create_iterator (att_list);
2676 !tny_iterator_is_done (iter);
2677 tny_iterator_next (iter)) {
2678 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2679 const gchar *att_id;
2680 tny_list_remove (priv->attachments, (GObject *) mime_part);
2682 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2684 if (tny_list_get_length (priv->attachments) == 0)
2685 gtk_widget_hide (priv->attachments_caption);
2686 att_id = tny_mime_part_get_content_id (mime_part);
2688 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2690 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2691 g_object_unref (mime_part);
2693 g_object_unref (iter);
2696 g_object_unref (att_list);
2698 /* if the last attachment has been removed, focus the Subject: field */
2699 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2700 gtk_widget_grab_focus (priv->subject_field);
2704 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2707 ModestMsgEditWindowPrivate *priv;
2708 GdkColor *new_color;
2709 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2711 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2712 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2715 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2717 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2719 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2721 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2726 font_size_clicked (GtkToolButton *button,
2727 ModestMsgEditWindow *window)
2729 ModestMsgEditWindowPrivate *priv;
2730 GtkWidget *selector, *dialog;
2732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2734 selector = hildon_touch_selector_new ();
2735 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2736 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2738 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2739 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2740 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2742 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2746 WPTextBufferFormat format;
2748 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2750 memset (&format, 0, sizeof (format));
2751 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2753 format.cs.font_size = TRUE;
2754 format.cs.text_position = TRUE;
2755 format.cs.font = TRUE;
2756 format.font_size = new_index;
2757 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2759 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2760 GINT_TO_POINTER (new_index)))
2761 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2763 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2764 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2765 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2766 size_text, "</span>", NULL);
2768 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2772 gtk_widget_destroy (dialog);
2774 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2779 font_face_clicked (GtkToolButton *button,
2780 ModestMsgEditWindow *window)
2782 ModestMsgEditWindowPrivate *priv;
2783 GtkWidget *selector, *dialog;
2784 GtkCellRenderer *renderer;
2786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2788 selector = hildon_touch_selector_new ();
2789 renderer = gtk_cell_renderer_text_new ();
2790 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2791 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2792 renderer, "family", 0, "text", 0, NULL);
2793 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2795 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2796 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2797 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2799 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2800 gint new_font_index;
2804 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2805 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2806 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2810 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2812 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2813 GINT_TO_POINTER(new_font_index)))
2814 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2816 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2817 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2819 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2823 gtk_tree_path_free (path);
2826 gtk_widget_destroy (dialog);
2828 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2833 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2836 ModestMsgEditWindowPrivate *priv = NULL;
2837 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2839 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2840 if (!priv->update_caption_visibility)
2843 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2845 gtk_widget_show (priv->cc_caption);
2847 gtk_widget_hide (priv->cc_caption);
2849 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2853 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2856 ModestMsgEditWindowPrivate *priv = NULL;
2857 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2859 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2860 if (!priv->update_caption_visibility)
2863 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2865 gtk_widget_show (priv->bcc_caption);
2867 gtk_widget_hide (priv->bcc_caption);
2869 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2873 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2874 ModestRecptEditor *editor)
2876 ModestMsgEditWindowPrivate *priv;
2878 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2879 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2881 /* we check for low-mem; in that case, show a warning, and don't allow
2882 * for the addressbook
2884 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2889 if (editor == NULL) {
2890 GtkWidget *view_focus;
2891 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2893 /* This code should be kept in sync with ModestRecptEditor. The
2894 textview inside the recpt editor is the one that really gets the
2895 focus. As it's inside a scrolled window, and this one inside the
2896 hbox recpt editor inherits from, we'll need to go up in the
2897 hierarchy to know if the text view is part of the recpt editor
2898 or if it's a different text entry */
2900 if (gtk_widget_get_parent (view_focus)) {
2901 GtkWidget *first_parent;
2903 first_parent = gtk_widget_get_parent (view_focus);
2904 if (gtk_widget_get_parent (first_parent) &&
2905 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2906 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2911 editor = MODEST_RECPT_EDITOR (priv->to_field);
2915 modest_address_book_select_addresses (editor);
2920 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2922 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2924 modest_msg_edit_window_open_addressbook (window, NULL);
2928 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2929 gboolean show_toolbar)
2931 ModestWindowPrivate *parent_priv;
2933 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2934 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2936 /* We can not just use the code of
2937 modest_msg_edit_window_setup_toolbar because it has a
2938 mixture of both initialization and creation code. */
2940 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2942 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2946 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2947 TnyHeaderFlags priority_flags)
2949 ModestMsgEditWindowPrivate *priv;
2950 ModestWindowPrivate *parent_priv;
2952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2955 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2957 if (priv->priority_flags != priority_flags) {
2958 GtkAction *priority_action = NULL;
2960 priv->priority_flags = priority_flags;
2962 switch (priority_flags) {
2963 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2964 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2965 MODEST_HEADER_ICON_HIGH,
2966 HILDON_ICON_SIZE_SMALL);
2967 gtk_widget_show (priv->priority_icon);
2968 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2969 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2971 case TNY_HEADER_FLAG_LOW_PRIORITY:
2972 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2973 MODEST_HEADER_ICON_LOW,
2974 HILDON_ICON_SIZE_SMALL);
2975 gtk_widget_show (priv->priority_icon);
2976 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2977 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2980 gtk_widget_hide (priv->priority_icon);
2981 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2982 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2985 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2986 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2988 gtk_widget_queue_resize (priv->subject_box);
2992 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2995 ModestMsgEditWindowPrivate *priv;
2996 ModestWindowPrivate *parent_priv;
2997 gint current_format;
2999 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3001 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3004 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3005 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3007 if (current_format != file_format) {
3008 switch (file_format) {
3009 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3010 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3011 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3013 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3017 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3018 response = gtk_dialog_run (GTK_DIALOG (dialog));
3019 gtk_widget_destroy (dialog);
3020 if (response == GTK_RESPONSE_OK) {
3021 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3023 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3024 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3029 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3030 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3031 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3036 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3039 ModestMsgEditWindowPrivate *priv;
3040 WPTextBufferFormat oldfmt, fmt;
3041 gint old_position = 0;
3045 GdkColor *color = NULL;
3046 gboolean bold, bold_set, italic, italic_set;
3047 gboolean underline, underline_set;
3048 gboolean strikethrough, strikethrough_set;
3049 gboolean position_set;
3050 gboolean font_size_set, font_set, color_set;
3053 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3056 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3057 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3058 GTK_WINDOW(dialog), GTK_WINDOW (window));
3060 /* First we get the currently selected font information */
3061 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3063 switch (oldfmt.text_position) {
3064 case TEXT_POSITION_NORMAL:
3067 case TEXT_POSITION_SUPERSCRIPT:
3075 g_object_set (G_OBJECT (dialog),
3076 "bold", oldfmt.bold != FALSE,
3077 "bold-set", !oldfmt.cs.bold,
3078 "underline", oldfmt.underline != FALSE,
3079 "underline-set", !oldfmt.cs.underline,
3080 "italic", oldfmt.italic != FALSE,
3081 "italic-set", !oldfmt.cs.italic,
3082 "strikethrough", oldfmt.strikethrough != FALSE,
3083 "strikethrough-set", !oldfmt.cs.strikethrough,
3084 "color", &oldfmt.color,
3085 "color-set", !oldfmt.cs.color,
3086 "size", wp_font_size[oldfmt.font_size],
3087 "size-set", !oldfmt.cs.font_size,
3088 "position", old_position,
3089 "position-set", !oldfmt.cs.text_position,
3090 "family", wp_get_font_name (oldfmt.font),
3091 "family-set", !oldfmt.cs.font,
3094 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3095 GTK_WINDOW (dialog), GTK_WINDOW (window));
3096 gtk_widget_show_all (dialog);
3097 priv->font_dialog = dialog;
3098 response = gtk_dialog_run (GTK_DIALOG (dialog));
3099 priv->font_dialog = NULL;
3100 if (response == GTK_RESPONSE_OK) {
3102 g_object_get( dialog,
3104 "bold-set", &bold_set,
3105 "underline", &underline,
3106 "underline-set", &underline_set,
3108 "italic-set", &italic_set,
3109 "strikethrough", &strikethrough,
3110 "strikethrough-set", &strikethrough_set,
3112 "color-set", &color_set,
3114 "size-set", &font_size_set,
3115 "family", &font_name,
3116 "family-set", &font_set,
3117 "position", &position,
3118 "position-set", &position_set,
3123 if (response == GTK_RESPONSE_OK) {
3124 memset(&fmt, 0, sizeof(fmt));
3130 fmt.italic = italic;
3131 fmt.cs.italic = TRUE;
3133 if (underline_set) {
3134 fmt.underline = underline;
3135 fmt.cs.underline = TRUE;
3137 if (strikethrough_set) {
3138 fmt.strikethrough = strikethrough;
3139 fmt.cs.strikethrough = TRUE;
3144 ? TEXT_POSITION_NORMAL
3145 : ( ( position == 1 )
3146 ? TEXT_POSITION_SUPERSCRIPT
3147 : TEXT_POSITION_SUBSCRIPT );
3148 fmt.cs.text_position = TRUE;
3149 fmt.font_size = oldfmt.font_size;
3153 fmt.cs.color = TRUE;
3156 fmt.font = wp_get_font_index(font_name,
3161 if (font_size_set) {
3162 fmt.cs.font_size = TRUE;
3163 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3165 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3166 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3168 gtk_widget_destroy (dialog);
3170 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3174 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3176 ModestMsgEditWindowPrivate *priv;
3178 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3179 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3181 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3183 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3184 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3188 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3190 ModestMsgEditWindowPrivate *priv;
3192 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3193 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3195 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3197 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3198 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3203 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3207 priv->can_undo = can_undo;
3211 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3213 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 priv->can_redo = can_redo;
3219 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3221 ModestMsgEditWindowPrivate *priv;
3222 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 return priv->can_undo;
3229 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3231 ModestMsgEditWindowPrivate *priv;
3232 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3235 return priv->can_redo;
3240 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3243 GtkTextIter match_start, match_end;
3245 if (image_id == NULL)
3248 gtk_text_buffer_get_start_iter (buffer, &iter);
3250 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3251 GSList *tags = gtk_text_iter_get_tags (&match_start);
3253 for (node = tags; node != NULL; node = g_slist_next (node)) {
3254 GtkTextTag *tag = (GtkTextTag *) node->data;
3255 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3256 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3257 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3259 offset = gtk_text_iter_get_offset (&match_start);
3260 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3261 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3265 gtk_text_iter_forward_char (&iter);
3270 message_is_empty (ModestMsgEditWindow *window)
3272 ModestMsgEditWindowPrivate *priv = NULL;
3274 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3275 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3278 * so we can ignore markup.
3280 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3283 count = gtk_text_buffer_get_char_count (buf);
3289 msg_body_focus (GtkWidget *focus,
3290 GdkEventFocus *event,
3294 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3295 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3296 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3301 recpt_field_changed (GtkTextBuffer *buffer,
3302 ModestMsgEditWindow *editor)
3304 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3305 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3309 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3311 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3312 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3316 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3319 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3320 GtkTextBuffer *buffer;
3322 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3323 gtk_text_buffer_set_modified (buffer, modified);
3324 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3325 gtk_text_buffer_set_modified (buffer, modified);
3326 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3327 gtk_text_buffer_set_modified (buffer, modified);
3328 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3332 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3334 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3335 const char *account_name;
3336 GtkTextBuffer *buffer;
3338 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3339 if (gtk_text_buffer_get_modified (buffer))
3341 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3342 if (gtk_text_buffer_get_modified (buffer))
3344 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3345 if (gtk_text_buffer_get_modified (buffer))
3347 if (gtk_text_buffer_get_modified (priv->text_buffer))
3350 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3351 if (priv->original_mailbox) {
3352 if (!account_name || strcmp (account_name, priv->original_mailbox))
3354 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3365 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3367 ModestMsgEditWindowPrivate *priv = NULL;
3369 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3370 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3372 /* check if there's no recipient added */
3373 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3374 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3375 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3376 /* no recipient contents, then select contacts */
3377 modest_msg_edit_window_open_addressbook (window, NULL);
3381 g_object_ref (window);
3382 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3383 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3384 g_object_unref (window);
3387 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3388 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3389 g_object_unref (window);
3392 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3393 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3394 g_object_unref (window);
3398 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3399 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3400 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3401 g_object_unref (window);
3408 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3409 ModestMsgEditWindow *window)
3411 modest_msg_edit_window_offer_attach_file (window);
3415 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3417 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3419 return priv->clipboard_text;
3423 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3425 ModestMsgEditWindow *window)
3427 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3428 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3431 /* It could happen that the window was already closed */
3432 if (!GTK_WIDGET_VISIBLE (window))
3435 g_object_ref (window);
3436 text = gtk_clipboard_wait_for_text (selection_clipboard);
3438 if (priv->clipboard_text != NULL) {
3439 g_free (priv->clipboard_text);
3441 priv->clipboard_text = text;
3443 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3445 g_object_unref (window);
3448 static gboolean clipboard_owner_change_idle (gpointer userdata)
3450 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3451 ModestMsgEditWindowPrivate *priv;
3453 gdk_threads_enter ();
3454 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3455 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3457 priv->clipboard_owner_idle = 0;
3458 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3459 gdk_threads_leave ();
3465 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3467 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3468 if (priv->clipboard_owner_idle == 0) {
3469 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3470 clipboard_owner_change_idle,
3471 g_object_ref (window),
3477 subject_field_move_cursor (GtkEntry *entry,
3478 GtkMovementStep step,
3483 /* It could happen that the window was already closed */
3484 if (!GTK_WIDGET_VISIBLE (window))
3487 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3491 update_window_title (ModestMsgEditWindow *window)
3493 ModestMsgEditWindowPrivate *priv = NULL;
3494 const gchar *subject;
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3497 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3498 if (subject == NULL || subject[0] == '\0')
3499 subject = _("mail_va_new_email");
3501 gtk_window_set_title (GTK_WINDOW (window), subject);
3507 body_insert_text (GtkTextBuffer *buffer,
3508 GtkTextIter *location,
3511 ModestMsgEditWindow *window)
3513 GtkTextIter end_iter;
3516 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3518 offset = gtk_text_iter_get_offset (&end_iter);
3520 if (offset + len > MAX_BODY_LENGTH) {
3521 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3522 if (offset < MAX_BODY_LENGTH)
3526 /* Prevent endless recursion */
3527 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3528 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3529 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3530 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3532 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3536 if (offset + len > MAX_BODY_LENGTH) {
3537 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3538 _CS("ckdg_ib_maximum_characters_reached"));
3543 subject_field_changed (GtkEditable *editable,
3544 ModestMsgEditWindow *window)
3546 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3547 update_window_title (window);
3548 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3549 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3550 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3553 subject_field_insert_text (GtkEditable *editable,
3555 gint new_text_length,
3557 ModestMsgEditWindow *window)
3559 GString *result = g_string_new ("");
3561 gint result_len = 0;
3562 const gchar *entry_text = NULL;
3565 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3566 old_length = g_utf8_strlen (entry_text, -1);
3568 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3569 gunichar c = g_utf8_get_char_validated (current, 8);
3570 /* Invalid unichar, stop */
3576 result = g_string_append_unichar (result, c);
3580 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3581 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3584 /* Prevent endless recursion */
3585 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3586 g_signal_emit_by_name (editable, "insert-text",
3587 (gpointer) result->str, (gpointer) result->len,
3588 (gpointer) position, (gpointer) window);
3589 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3593 if (result_len + old_length > 1000) {
3594 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3595 _CS("ckdg_ib_maximum_characters_reached"));
3597 g_string_free (result, TRUE);
3601 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3604 ModestMsgEditWindowPrivate *priv = NULL;
3606 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3607 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3609 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3612 gtk_widget_show_all (priv->find_toolbar);
3613 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3615 gtk_widget_hide_all (priv->find_toolbar);
3616 gtk_widget_grab_focus (priv->msg_body);
3621 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3623 GtkTextIter *match_start,
3624 GtkTextIter *match_end)
3626 GtkTextIter end_iter;
3627 gchar *str_casefold;
3630 gchar *range_casefold;
3633 gboolean result = FALSE;
3640 gtk_text_iter_forward_to_end (&end_iter);
3642 str_casefold = g_utf8_casefold (str, -1);
3643 str_chars_n = strlen (str);
3645 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3646 range_casefold = g_utf8_casefold (range_text, -1);
3647 range_chars_n = strlen (range_casefold);
3649 if (range_chars_n < str_chars_n) {
3650 g_free (str_casefold);
3651 g_free (range_text);
3652 g_free (range_casefold);
3656 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3657 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3658 if (!g_utf8_collate (range_subtext, str_casefold)) {
3659 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3661 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3662 match_start, match_end, NULL)) {
3663 g_warning ("Matched string with collate, but not matched in model");
3665 g_free (found_text);
3667 g_free (range_subtext);
3671 g_free (str_casefold);
3672 g_free (range_text);
3673 g_free (range_casefold);
3680 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3681 ModestMsgEditWindow *window)
3683 gchar *current_search = NULL;
3684 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3686 GtkTextIter selection_start, selection_end;
3687 GtkTextIter match_start, match_end;
3688 gboolean continue_search = FALSE;
3690 if (message_is_empty (window)) {
3691 g_free (priv->last_search);
3692 priv->last_search = NULL;
3693 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3697 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3698 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3699 g_free (current_search);
3700 g_free (priv->last_search);
3701 priv->last_search = NULL;
3702 /* Information banner about empty search */
3703 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3707 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3708 continue_search = TRUE;
3710 g_free (priv->last_search);
3711 priv->last_search = g_strdup (current_search);
3714 if (continue_search) {
3715 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3716 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3717 &match_start, &match_end);
3719 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3721 GtkTextIter buffer_start;
3722 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3723 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3724 &match_start, &match_end);
3726 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3729 /* Mark as selected the string found in search */
3731 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3732 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3733 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3735 g_free (priv->last_search);
3736 priv->last_search = NULL;
3738 g_free (current_search);
3742 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3744 ModestMsgEditWindowPrivate *priv;
3746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3751 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3754 ModestMsgEditWindowPrivate *priv;
3756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3761 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3762 ModestMsgEditWindow *window)
3764 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3768 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3771 ModestMsgEditWindowPrivate *priv;
3772 TnyHeader *header = NULL;
3774 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3775 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3779 if (priv->draft_msg != NULL) {
3780 g_object_unref (priv->draft_msg);
3783 if (draft != NULL) {
3784 g_object_ref (draft);
3785 header = tny_msg_get_header (draft);
3786 if (priv->msg_uid) {
3787 g_free (priv->msg_uid);
3788 priv->msg_uid = NULL;
3790 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3793 priv->draft_msg = draft;
3797 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3798 GtkTextIter *start, GtkTextIter *end,
3801 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3802 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3805 if (tag == NULL) return;
3806 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3807 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3808 replace_with_images (window, priv->images);
3813 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3816 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3818 g_return_if_fail (TNY_IS_MIME_PART (part));
3819 tny_list_prepend (priv->attachments, (GObject *) part);
3820 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3821 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3822 gtk_widget_show_all (priv->attachments_caption);
3823 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3827 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3829 ModestMsgEditWindowPrivate *priv;
3831 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3832 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3834 return priv->msg_uid;
3838 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3839 ModestMsgEditWindowWidgetType widget_type)
3841 ModestMsgEditWindowPrivate *priv;
3843 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3846 switch (widget_type) {
3847 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3848 return priv->msg_body;
3850 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3851 return priv->to_field;
3853 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3854 return priv->cc_field;
3856 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3857 return priv->bcc_field;
3859 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3860 return priv->subject_field;
3862 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3863 return priv->attachments_view;
3871 remove_tags (WPTextBuffer *buffer)
3873 GtkTextIter start, end;
3875 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3876 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3878 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3882 on_account_removed (TnyAccountStore *account_store,
3883 TnyAccount *account,
3886 /* Do nothing if it's a store account, because we use the
3887 transport to send the messages */
3888 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3889 const gchar *parent_acc = NULL;
3890 const gchar *our_acc = NULL;
3892 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3893 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3894 /* Close this window if I'm showing a message of the removed account */
3895 if (strcmp (parent_acc, our_acc) == 0)
3896 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3900 static void update_signature (ModestMsgEditWindow *self,
3901 const gchar *old_account,
3902 const gchar *new_account)
3904 ModestMsgEditWindowPrivate *priv;
3905 gboolean has_old_signature, has_new_signature;
3907 GtkTextIter match_start, match_end;
3908 ModestAccountMgr *mgr;
3910 gchar *full_signature;
3912 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3914 gtk_text_buffer_begin_user_action (priv->text_buffer);
3916 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3917 mgr = modest_runtime_get_account_mgr ();
3921 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3922 if (has_old_signature) {
3923 full_signature = g_strconcat ("\n--\n", signature, NULL);
3924 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3925 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3927 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3928 &match_start, &match_end, NULL)) {
3931 g_free (full_signature);
3936 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3937 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3938 if (has_new_signature) {
3939 full_signature = g_strconcat ("\n--\n", signature, NULL);
3940 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3941 g_free (full_signature);
3944 gtk_text_buffer_end_user_action (priv->text_buffer);
3948 from_field_changed (HildonPickerButton *button,
3949 ModestMsgEditWindow *self)
3951 ModestMsgEditWindowPrivate *priv;
3952 gchar *old_account, *new_account;
3954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3956 old_account = priv->last_from_account;
3957 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3958 new_account = priv->last_from_account;
3960 update_signature (self, old_account, new_account);
3964 typedef struct _MessageSettingsHelper {
3965 ModestMsgEditWindow *window;
3966 GSList *priority_group;
3967 GSList *format_group;
3968 GtkToggleButton *current_priority;
3969 GtkToggleButton *current_format;
3970 } MessageSettingsHelper;
3973 on_priority_toggle (GtkToggleButton *button,
3974 MessageSettingsHelper *helper)
3977 ModestMsgEditWindowPrivate *priv;
3979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3980 if (gtk_toggle_button_get_active (button)) {
3982 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3983 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3984 if ((node_button != button) &&
3985 gtk_toggle_button_get_active (node_button)) {
3986 gtk_toggle_button_set_active (node_button, FALSE);
3989 helper->current_priority = button;
3991 gboolean found = FALSE;
3992 /* If no one is active, activate it again */
3993 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3994 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3995 if (gtk_toggle_button_get_active (node_button)) {
4001 gtk_toggle_button_set_active (button, TRUE);
4007 on_format_toggle (GtkToggleButton *button,
4008 MessageSettingsHelper *helper)
4011 ModestMsgEditWindowPrivate *priv;
4013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4014 if (gtk_toggle_button_get_active (button)) {
4016 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4017 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4018 if ((node_button != button) &&
4019 gtk_toggle_button_get_active (node_button)) {
4020 gtk_toggle_button_set_active (node_button, FALSE);
4023 helper->current_format = button;
4025 gboolean found = FALSE;
4026 /* If no one is active, activate it again */
4027 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4028 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4029 if (gtk_toggle_button_get_active (node_button)) {
4035 gtk_toggle_button_set_active (button, TRUE);
4042 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4047 GtkWidget *priority_hbox;
4048 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4049 GtkWidget *captioned;
4050 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4051 GtkWidget *format_hbox;
4052 GtkWidget *html_toggle, *text_toggle;
4053 ModestMsgEditWindowPrivate *priv;
4054 MessageSettingsHelper helper = {0,};
4056 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4058 helper.window = window;
4059 helper.priority_group = NULL;
4060 helper.format_group = NULL;
4062 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4063 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4065 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4066 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4067 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4068 vbox = gtk_vbox_new (FALSE, 0);
4069 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4070 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4071 gtk_container_add (GTK_CONTAINER (align), vbox);
4072 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4073 gtk_widget_show (align);
4074 gtk_widget_show (vbox);
4076 /* Priority toggles */
4077 priority_hbox = gtk_hbox_new (TRUE, 0);
4078 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4079 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4080 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4081 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4082 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4083 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4084 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4085 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4086 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4087 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4088 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4089 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4090 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4091 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4092 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4093 gtk_widget_show_all (priority_hbox);
4094 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4095 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4096 gtk_widget_show (captioned);
4097 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4099 /* format toggles */
4100 format_hbox = gtk_hbox_new (TRUE, 0);
4101 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4102 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4103 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4104 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4105 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4106 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4107 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4108 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4109 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4110 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4111 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4112 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4113 gtk_widget_show_all (format_hbox);
4114 gtk_widget_show (format_hbox);
4115 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4118 g_object_unref (title_sizegroup);
4119 g_object_unref (value_sizegroup);
4121 /* Set current values */
4122 switch (priv->priority_flags) {
4123 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4124 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4125 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4127 case TNY_HEADER_FLAG_LOW_PRIORITY:
4128 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4129 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4132 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4133 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4137 switch (modest_msg_edit_window_get_format (window)) {
4138 case MODEST_MSG_EDIT_FORMAT_TEXT:
4139 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4140 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4142 case MODEST_MSG_EDIT_FORMAT_HTML:
4144 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4145 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4149 /* Signal connects */
4150 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4151 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4152 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4153 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4154 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4156 /* Save settings if the user clicked on done */
4157 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4158 TnyHeaderFlags flags;
4159 ModestMsgEditFormat old_format, new_format;
4161 /* Set priority flags */
4162 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4163 if (priv->priority_flags != flags)
4164 modest_msg_edit_window_set_priority_flags (window, flags);
4166 /* Set edit format */
4167 old_format = modest_msg_edit_window_get_format (window);
4168 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4169 if (old_format != new_format) {
4170 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4171 modest_msg_edit_window_set_file_format (window, file_format);
4175 gtk_widget_destroy (dialog);
4176 g_slist_free (helper.priority_group);
4180 on_message_settings (GtkAction *action,
4181 ModestMsgEditWindow *window)
4183 modest_msg_edit_window_show_msg_settings_dialog (window);
4187 on_cc_button_toggled (HildonCheckButton *button,
4188 ModestMsgEditWindow *window)
4190 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4192 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4193 hildon_check_button_get_active (button));
4197 on_bcc_button_toggled (HildonCheckButton *button,
4198 ModestMsgEditWindow *window)
4200 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4202 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4203 hildon_check_button_get_active (button));
4207 setup_menu (ModestMsgEditWindow *self)
4209 ModestMsgEditWindowPrivate *priv = NULL;
4211 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4215 /* Settings menu buttons */
4216 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4217 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4219 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4220 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4221 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4223 priv->cc_button = hildon_check_button_new (0);
4224 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4225 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4227 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4229 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4230 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4231 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4232 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4234 priv->bcc_button = hildon_check_button_new (0);
4235 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4236 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4238 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4240 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4241 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4242 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4243 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4245 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4246 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4247 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4248 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4249 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4250 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4251 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4252 APP_MENU_CALLBACK (on_message_settings),
4254 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4255 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4260 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4261 const gchar *label, GtkWidget *control)
4263 GtkWidget *abook_button;
4267 box = gtk_hbox_new (FALSE, 0);
4269 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4270 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4272 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4273 gtk_button_set_label (GTK_BUTTON (abook_button), label);
4275 gtk_container_add (GTK_CONTAINER (align), abook_button);
4276 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4277 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4278 if (title_size_group)
4279 gtk_size_group_add_widget (title_size_group, abook_button);
4280 if (value_size_group)
4281 gtk_size_group_add_widget (value_size_group, control);