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_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
876 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.5, 0.5);
878 priv->to_field = modest_recpt_editor_new ();
879 priv->cc_field = modest_recpt_editor_new ();
880 priv->bcc_field = modest_recpt_editor_new ();
881 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
882 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
883 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
884 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
885 priv->priority_icon = gtk_image_new ();
886 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
887 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
888 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
889 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
890 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
891 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
892 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
893 priv->add_attachment_button = hildon_button_new (MODEST_EDITABLE_SIZE, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
894 gtk_widget_set_size_request (priv->add_attachment_button, ATTACHMENT_BUTTON_WIDTH, -1);
895 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
896 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
897 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, HILDON_ICON_SIZE_FINGER);
898 hildon_button_set_image (HILDON_BUTTON (priv->add_attachment_button), attachment_icon);
899 add_attachment_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
900 gtk_alignment_set_padding (GTK_ALIGNMENT (add_attachment_align), 0, 0, MODEST_MARGIN_DEFAULT, 0);
901 gtk_container_add (GTK_CONTAINER (add_attachment_align), priv->add_attachment_button);
902 gtk_box_pack_start (GTK_BOX (priv->subject_box), add_attachment_align, FALSE, FALSE, 0);
903 priv->attachments_view = modest_attachments_view_new (NULL);
904 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
905 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
907 priv->header_box = gtk_vbox_new (FALSE, 0);
909 to_caption = _create_addressbook_box
910 (title_size_group, value_size_group,
911 _("mail_va_to"), priv->to_field);
912 priv->cc_caption = _create_addressbook_box
913 (title_size_group, value_size_group,
914 _("mail_va_cc"), priv->cc_field);
915 priv->bcc_caption = _create_addressbook_box
916 (title_size_group, value_size_group,
917 _("mail_va_hotfix1"), priv->bcc_field);
918 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
919 _("mail_va_subject"), FALSE, priv->subject_box);
920 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
921 _("mail_va_attachment"),
923 priv->attachments_view,
924 HILDON_SIZE_AUTO_WIDTH |
925 HILDON_SIZE_AUTO_HEIGHT);
926 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
927 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
928 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
929 g_object_unref (title_size_group);
930 g_object_unref (value_size_group);
932 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
933 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
934 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
935 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
936 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
937 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
938 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
940 init_wp_text_view_style ();
942 priv->msg_body = modest_wp_text_view_new ();
945 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
946 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
947 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
948 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
949 #if (GTK_MINOR_VERSION >= 10)
950 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
951 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
953 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
954 deserialize_type, TRUE);
956 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
958 priv->find_toolbar = hildon_find_toolbar_new (NULL);
959 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
961 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
963 priv->pannable = hildon_pannable_area_new ();
965 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
967 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
968 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
969 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
971 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
972 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
973 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
975 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
976 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
978 window_box = gtk_vbox_new (FALSE, 0);
979 gtk_container_add (GTK_CONTAINER(obj), window_box);
981 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
983 /* Set window icon */
984 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
986 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
987 g_object_unref (window_icon);
992 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
994 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
996 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
997 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
998 priv->clipboard_change_handler_id))
999 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1000 priv->clipboard_change_handler_id);
1001 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1002 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1003 priv->default_clipboard_change_handler_id))
1004 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1005 priv->default_clipboard_change_handler_id);
1007 if (priv->account_removed_handler_id &&
1008 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1009 priv->account_removed_handler_id))
1010 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1011 priv->account_removed_handler_id);
1015 modest_msg_edit_window_finalize (GObject *obj)
1017 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1019 /* Sanity check: shouldn't be needed, the window mgr should
1020 call this function before */
1021 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1023 if (priv->font_dialog != NULL) {
1024 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1027 if (priv->clipboard_text != NULL) {
1028 g_free (priv->clipboard_text);
1029 priv->clipboard_text = NULL;
1032 if (priv->draft_msg != NULL) {
1033 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1034 if (TNY_IS_HEADER (header)) {
1035 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1036 modest_window_mgr_unregister_header (mgr, header);
1038 g_object_unref (priv->draft_msg);
1039 priv->draft_msg = NULL;
1041 if (priv->outbox_msg != NULL) {
1042 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1043 if (TNY_IS_HEADER (header)) {
1044 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1045 modest_window_mgr_unregister_header (mgr, header);
1047 g_object_unref (priv->outbox_msg);
1048 priv->outbox_msg = NULL;
1050 if (priv->correct_scroll_idle > 0) {
1051 g_source_remove (priv->correct_scroll_idle);
1052 priv->correct_scroll_idle = 0;
1054 if (priv->scroll_drag_timeout_id > 0) {
1055 g_source_remove (priv->scroll_drag_timeout_id);
1056 priv->scroll_drag_timeout_id = 0;
1058 if (priv->clipboard_owner_idle > 0) {
1059 g_source_remove (priv->clipboard_owner_idle);
1060 priv->clipboard_owner_idle = 0;
1062 if (priv->original_account_name)
1063 g_free (priv->original_account_name);
1064 if (priv->original_mailbox)
1065 g_free (priv->original_mailbox);
1066 g_free (priv->msg_uid);
1067 g_free (priv->last_search);
1068 g_free (priv->references);
1069 g_free (priv->in_reply_to);
1070 g_object_unref (priv->faces_model);
1071 g_object_unref (priv->sizes_model);
1072 g_object_unref (priv->attachments);
1073 g_object_unref (priv->images);
1075 /* This had to stay alive for as long as the picker that used it: */
1076 modest_pair_list_free (priv->from_field_protos);
1078 G_OBJECT_CLASS(parent_class)->finalize (obj);
1082 pixbuf_size_prepared (GdkPixbufLoader *loader,
1085 ModestMsgEditWindow *self)
1087 gint new_height, new_width;
1090 new_height = height;
1094 if (width > IMAGE_MAX_WIDTH) {
1095 new_height = height * IMAGE_MAX_WIDTH / width;
1096 new_width = IMAGE_MAX_WIDTH;
1099 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1103 pixbuf_from_stream (TnyStream *stream,
1104 const gchar *mime_type,
1105 guint64 *stream_size,
1106 ModestMsgEditWindow *self)
1108 GdkPixbufLoader *loader;
1111 GError *error = NULL;
1115 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1117 if (loader == NULL) {
1122 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1124 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1126 tny_stream_reset (TNY_STREAM (stream));
1127 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1128 unsigned char read_buffer[128];
1130 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1132 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1135 /* Allow some UI responsiveness */
1136 while (gtk_events_pending ())
1137 gtk_main_iteration ();
1139 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1141 gdk_pixbuf_loader_close (loader, &error);
1144 g_error_free (error);
1145 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1147 g_object_ref (pixbuf);
1148 g_object_unref (loader);
1153 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1154 GdkPixbuf *new_pixbuf;
1156 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1157 gdk_pixbuf_get_width (pixbuf);
1158 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1159 g_object_unref (pixbuf);
1160 pixbuf = new_pixbuf;
1164 *stream_size = size;
1170 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1172 ModestMsgEditWindowPrivate *priv;
1175 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1177 g_object_ref (self);
1178 for (iter = tny_list_create_iterator (attachments);
1179 !tny_iterator_is_done (iter);
1180 tny_iterator_next (iter)) {
1181 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1182 const gchar *cid = tny_mime_part_get_content_id (part);
1183 const gchar *mime_type = tny_mime_part_get_content_type (part);
1184 if ((cid != NULL)&&(mime_type != NULL)) {
1185 guint64 stream_size;
1186 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1187 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1190 g_object_unref (stream);
1192 if (pixbuf != NULL) {
1193 priv->images_count ++;
1194 priv->images_size += stream_size;
1195 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1196 g_object_unref (pixbuf);
1199 g_object_unref (part);
1201 g_object_unref (iter);
1202 g_object_unref (self);
1206 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1208 TnyMimePart *parent = NULL;
1209 const gchar *content_type = NULL;
1210 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1212 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1214 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1215 parent = g_object_ref (msg);
1216 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1217 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1220 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1221 iter = tny_list_create_iterator (parts);
1222 while (!tny_iterator_is_done (iter)) {
1224 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1225 content_type = tny_mime_part_get_content_type (part);
1226 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1230 g_object_unref (part);
1232 tny_iterator_next (iter);
1234 g_object_unref (iter);
1235 g_object_unref (parts);
1238 if (parent != NULL) {
1239 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1242 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1243 iter = tny_list_create_iterator (parts);
1244 while (!tny_iterator_is_done (iter)) {
1246 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1247 content_type = tny_mime_part_get_content_type (part);
1248 if (content_type && g_str_has_prefix (content_type, "image/")) {
1249 tny_list_prepend (priv->images, (GObject *) part);
1251 g_object_unref (part);
1252 tny_iterator_next (iter);
1254 g_object_unref (iter);
1255 g_object_unref (parts);
1256 g_object_unref (parent);
1261 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1264 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1266 for (iter = tny_list_create_iterator (attachments) ;
1267 !tny_iterator_is_done (iter);
1268 tny_iterator_next (iter)) {
1269 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1270 const gchar *cid = tny_mime_part_get_content_id (part);
1272 char *invalid = NULL;
1273 gint int_cid = strtol (cid, &invalid, 10);
1274 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1275 priv->next_cid = int_cid + 1;
1278 g_object_unref (part);
1280 g_object_unref (iter);
1284 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1287 gchar *to, *cc, *bcc, *subject;
1289 ModestMsgEditWindowPrivate *priv;
1290 ModestWindowPrivate *parent_priv;
1292 TnyHeaderFlags priority_flags;
1293 TnyFolder *msg_folder;
1294 gboolean is_html = FALSE;
1295 gboolean field_view_set;
1297 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1298 g_return_if_fail (TNY_IS_MSG (msg));
1300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1301 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1303 header = tny_msg_get_header (msg);
1304 to = tny_header_dup_to (header);
1305 cc = tny_header_dup_cc (header);
1306 bcc = tny_header_dup_bcc (header);
1307 subject = tny_header_dup_subject (header);
1309 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1310 priority_flags = tny_header_get_priority (header);
1313 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1315 field_view_set = TRUE;
1317 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1318 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1319 gtk_widget_show (priv->cc_caption);
1320 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1321 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1322 gtk_widget_hide (priv->cc_caption);
1323 field_view_set = FALSE;
1325 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1327 field_view_set = TRUE;
1329 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1330 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1331 gtk_widget_show (priv->bcc_caption);
1332 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1333 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1334 gtk_widget_hide (priv->bcc_caption);
1335 field_view_set = FALSE;
1337 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1341 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1342 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1345 update_window_title (self);
1347 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1348 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1350 if ((body == NULL)||(body[0] == '\0')) {
1352 body = modest_text_utils_convert_to_html ("");
1355 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1356 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1359 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1362 /* Add attachments to the view */
1363 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1364 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1365 if (tny_list_get_length (priv->attachments) == 0) {
1366 gtk_widget_hide (priv->attachments_caption);
1368 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1369 gtk_widget_show_all (priv->attachments_caption);
1371 get_related_images (self, msg);
1372 update_next_cid (self, priv->attachments);
1373 update_next_cid (self, priv->images);
1374 replace_with_images (self, priv->images);
1376 if (preserve_is_rich && !is_html) {
1377 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1378 /* Get the default format required from configuration */
1379 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1380 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1383 /* Set the default focus depending on having already a To: field or not */
1384 if ((!to)||(*to == '\0')) {
1385 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1387 gtk_widget_grab_focus (priv->msg_body);
1390 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1392 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1393 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1395 modest_msg_edit_window_set_modified (self, FALSE);
1397 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1398 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1399 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1400 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1402 if (priv->msg_uid) {
1403 g_free (priv->msg_uid);
1404 priv->msg_uid = NULL;
1407 /* we should set a reference to the incoming message if it is a draft */
1408 msg_folder = tny_msg_get_folder (msg);
1410 if (modest_tny_folder_is_local_folder (msg_folder)) {
1411 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1412 if (type == TNY_FOLDER_TYPE_INVALID)
1413 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1415 if (type == TNY_FOLDER_TYPE_DRAFTS)
1416 priv->draft_msg = g_object_ref(msg);
1417 if (type == TNY_FOLDER_TYPE_OUTBOX)
1418 priv->outbox_msg = g_object_ref(msg);
1419 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1421 g_object_unref (msg_folder);
1432 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1434 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1435 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1436 GtkWidget *placeholder;
1437 GtkWidget *tool_item;
1442 GtkWidget *sizes_menu;
1443 GtkWidget *fonts_menu;
1449 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1450 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1451 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1452 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1454 /* Font color placeholder */
1455 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1456 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1459 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1460 priv->font_color_button = hildon_color_button_new ();
1461 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1462 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1463 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1464 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1467 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1468 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1470 G_CALLBACK (modest_msg_edit_window_color_button_change),
1473 /* Font size and face placeholder */
1474 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1475 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1477 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1478 priv->size_tool_button_label = gtk_label_new (NULL);
1479 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1480 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1481 size_text, "</span>", NULL);
1482 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1483 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1485 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1486 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1487 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1488 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1489 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1490 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1491 gtk_widget_set_sensitive (arrow, FALSE);
1492 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1493 sizes_menu = gtk_menu_new ();
1494 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1495 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1498 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1499 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1501 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1505 if (wp_font_size[size_index] == 12)
1506 priv->current_size_index = size_index;
1510 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1511 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1512 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1513 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1514 priv->font_size_toolitem = tool_item;
1517 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1518 priv->font_tool_button_label = gtk_label_new (NULL);
1519 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1520 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1521 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1523 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1524 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1525 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1526 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1527 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1528 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1529 gtk_widget_set_sensitive (arrow, FALSE);
1530 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1531 fonts_menu = gtk_menu_new ();
1532 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1533 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1536 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1538 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1539 0, wp_get_font_name (font_index),
1542 if (font_index == DEFAULT_FONT)
1543 priv->current_face_index = font_index;
1545 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1546 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1547 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1548 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1549 priv->font_face_toolitem = tool_item;
1551 /* Set expand and homogeneous for remaining items */
1552 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1553 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1554 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1555 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1556 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1557 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1558 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1559 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1560 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1562 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1563 will not show the tool items added to the placeholders) */
1564 gtk_widget_show_all (parent_priv->toolbar);
1566 /* Set the no show all *after* showing all items. We do not
1567 want the toolbar to be shown with a show all because it
1568 could go agains the gconf setting regarding showing or not
1569 the toolbar of the editor window */
1570 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1576 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1579 ModestWindowPrivate *parent_priv;
1580 ModestMsgEditWindowPrivate *priv;
1581 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1582 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1583 ModestWindowMgr *mgr = NULL;
1585 g_return_val_if_fail (msg, NULL);
1586 g_return_val_if_fail (account_name, NULL);
1588 mgr = modest_runtime_get_window_mgr ();
1590 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1593 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1595 /* Menubar. Update the state of some toggles */
1596 priv->from_field_protos = get_transports ();
1597 priv->original_mailbox = NULL;
1598 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1599 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1600 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1601 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1602 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1603 priv->original_mailbox = g_strdup (mailbox);
1604 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1605 /* We set the first mailbox as the active mailbox */
1606 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1607 if (priv->original_mailbox != NULL)
1608 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1609 (gpointer) priv->original_mailbox);
1611 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1612 (gpointer) account_name);
1614 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1616 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1617 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1619 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1620 hildon_touch_selector_get_current_text
1621 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1622 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1623 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1626 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1628 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1630 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1631 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1633 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1635 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1636 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1637 /* Add common dimming rules */
1638 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1639 modest_msg_edit_window_toolbar_dimming_entries,
1640 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1641 MODEST_WINDOW (obj));
1642 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1643 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1644 MODEST_WINDOW (obj));
1645 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1646 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1647 MODEST_WINDOW (obj));
1648 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1649 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1650 MODEST_WINDOW (obj));
1651 /* Insert dimming rules group for this window */
1652 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1653 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1655 /* Setup app menu */
1656 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1658 /* Checks the dimming rules */
1659 g_object_unref (toolbar_rules_group);
1660 g_object_unref (clipboard_rules_group);
1661 gtk_widget_hide (priv->priority_icon);
1662 gtk_widget_queue_resize (priv->subject_box);
1663 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1665 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1667 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1668 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1669 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1670 priv->update_caption_visibility = TRUE;
1672 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1674 /* Track account-removed signal, this window should be closed
1675 in the case we're creating a mail associated to the account
1677 priv->account_removed_handler_id =
1678 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1680 G_CALLBACK(on_account_removed),
1683 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1685 return (ModestWindow*) obj;
1689 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1691 GString **string_buffer = (GString **) user_data;
1693 *string_buffer = g_string_append (*string_buffer, buffer);
1699 * @result: A new string which should be freed with g_free().
1702 get_formatted_data (ModestMsgEditWindow *edit_window)
1704 ModestMsgEditWindowPrivate *priv;
1705 GString *string_buffer = g_string_new ("");
1707 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1709 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1711 modest_text_utils_hyperlinkify (string_buffer);
1713 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1715 return g_string_free (string_buffer, FALSE);
1720 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1723 const gchar *account_name;
1724 ModestMsgEditWindowPrivate *priv;
1725 TnyIterator *att_iter;
1726 const gchar *picker_active_id;
1728 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1730 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1732 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1733 g_return_val_if_fail (picker_active_id, NULL);
1734 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1736 /* don't free these (except from) */
1737 data = g_slice_new0 (MsgData);
1738 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1739 data->account_name = g_strdup (account_name);
1740 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1741 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1742 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1743 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1744 data->references = g_strdup (priv->references);
1745 data->in_reply_to = g_strdup (priv->in_reply_to);
1746 if (priv->draft_msg) {
1747 data->draft_msg = g_object_ref (priv->draft_msg);
1748 } else if (priv->outbox_msg) {
1749 data->draft_msg = g_object_ref (priv->outbox_msg);
1751 data->draft_msg = NULL;
1754 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1756 gtk_text_buffer_get_bounds (buf, &b, &e);
1757 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1759 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1760 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1762 data->html_body = NULL;
1764 /* deep-copy the data */
1765 att_iter = tny_list_create_iterator (priv->attachments);
1766 data->attachments = NULL;
1767 while (!tny_iterator_is_done (att_iter)) {
1768 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1769 if (!(TNY_IS_MIME_PART(part))) {
1770 g_warning ("strange data in attachment list");
1771 g_object_unref (part);
1772 tny_iterator_next (att_iter);
1775 data->attachments = g_list_append (data->attachments,
1777 tny_iterator_next (att_iter);
1779 g_object_unref (att_iter);
1781 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1782 att_iter = tny_list_create_iterator (priv->images);
1783 data->images = NULL;
1784 while (!tny_iterator_is_done (att_iter)) {
1785 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1787 if (!(TNY_IS_MIME_PART(part))) {
1788 g_warning ("strange data in attachment list");
1789 g_object_unref (part);
1790 tny_iterator_next (att_iter);
1793 cid = tny_mime_part_get_content_id (part);
1795 gchar *image_tag_id;
1796 GtkTextTag *image_tag;
1798 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1799 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1800 g_free (image_tag_id);
1802 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1804 ((gtk_text_iter_has_tag (&iter, image_tag))||
1805 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1806 data->images = g_list_append (data->images,
1807 g_object_ref (part));
1809 g_object_unref (part);
1810 tny_iterator_next (att_iter);
1812 g_object_unref (att_iter);
1814 data->priority_flags = priv->priority_flags;
1821 unref_gobject (GObject *obj, gpointer data)
1823 if (!G_IS_OBJECT(obj))
1825 g_object_unref (obj);
1829 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1832 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1840 g_free (data->from);
1841 g_free (data->subject);
1842 g_free (data->plain_body);
1843 g_free (data->html_body);
1844 g_free (data->account_name);
1845 g_free (data->references);
1846 g_free (data->in_reply_to);
1848 if (data->draft_msg != NULL) {
1849 g_object_unref (data->draft_msg);
1850 data->draft_msg = NULL;
1853 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1854 g_list_free (data->attachments);
1855 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1856 g_list_free (data->images);
1858 g_slice_free (MsgData, data);
1862 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1864 guint64 *parts_size)
1866 ModestMsgEditWindowPrivate *priv;
1868 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1870 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1872 /* TODO: add images */
1873 *parts_size += priv->images_size;
1874 *parts_count += priv->images_count;
1879 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1882 ModestMsgEditWindowPrivate *priv = NULL;
1883 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1887 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1889 return MODEST_MSG_EDIT_FORMAT_HTML;
1891 return MODEST_MSG_EDIT_FORMAT_TEXT;
1895 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1896 ModestMsgEditFormat format)
1898 ModestMsgEditWindowPrivate *priv;
1900 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1901 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1904 case MODEST_MSG_EDIT_FORMAT_HTML:
1905 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1907 case MODEST_MSG_EDIT_FORMAT_TEXT:
1908 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1911 g_return_if_reached ();
1915 ModestMsgEditFormatState *
1916 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1918 ModestMsgEditFormatState *format_state = NULL;
1919 ModestMsgEditWindowPrivate *priv;
1920 WPTextBufferFormat *buffer_format;
1922 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1924 buffer_format = g_new0 (WPTextBufferFormat, 1);
1925 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1927 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1929 format_state = g_new0 (ModestMsgEditFormatState, 1);
1930 format_state->bold = buffer_format->bold&0x1;
1931 format_state->italics = buffer_format->italic&0x1;
1932 format_state->bullet = buffer_format->bullet&0x1;
1933 format_state->color = buffer_format->color;
1934 format_state->font_size = buffer_format->font_size;
1935 format_state->font_family = wp_get_font_name (buffer_format->font);
1936 format_state->justification = buffer_format->justification;
1937 g_free (buffer_format);
1939 return format_state;
1944 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1945 const ModestMsgEditFormatState *format_state)
1947 ModestMsgEditWindowPrivate *priv;
1948 WPTextBufferFormat *buffer_format;
1949 WPTextBufferFormat *current_format;
1951 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1952 g_return_if_fail (format_state != NULL);
1954 buffer_format = g_new0 (WPTextBufferFormat, 1);
1955 current_format = g_new0 (WPTextBufferFormat, 1);
1957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1958 gtk_widget_grab_focus (priv->msg_body);
1959 buffer_format->bold = (format_state->bold != FALSE);
1960 buffer_format->italic = (format_state->italics != FALSE);
1961 buffer_format->color = format_state->color;
1962 buffer_format->font_size = format_state->font_size;
1963 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1964 buffer_format->justification = format_state->justification;
1965 buffer_format->bullet = format_state->bullet;
1967 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1969 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1970 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1971 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1972 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1973 buffer_format->cs.font = (buffer_format->font != current_format->font);
1974 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1975 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1977 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1978 if (buffer_format->cs.bold) {
1979 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1980 GINT_TO_POINTER (buffer_format->bold&0x1));
1982 if (buffer_format->cs.italic) {
1983 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1984 GINT_TO_POINTER (buffer_format->italic&0x1));
1986 if (buffer_format->cs.color) {
1987 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1988 GINT_TO_POINTER (&(buffer_format->color)));
1990 if (buffer_format->cs.font_size) {
1991 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1992 GINT_TO_POINTER (buffer_format->font_size));
1994 if (buffer_format->cs.justification) {
1995 switch (buffer_format->justification) {
1996 case GTK_JUSTIFY_LEFT:
1997 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1998 GINT_TO_POINTER(TRUE));
2000 case GTK_JUSTIFY_CENTER:
2001 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2002 GINT_TO_POINTER(TRUE));
2004 case GTK_JUSTIFY_RIGHT:
2005 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2006 GINT_TO_POINTER(TRUE));
2013 if (buffer_format->cs.font) {
2014 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2015 GINT_TO_POINTER (buffer_format->font));
2017 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2018 if (buffer_format->cs.bullet) {
2019 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2020 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2022 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2024 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2026 g_free (buffer_format);
2027 g_free (current_format);
2029 /* Check dimming rules */
2030 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2031 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2035 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2037 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2039 ModestWindowPrivate *parent_priv;
2040 ModestMsgEditWindowPrivate *priv;
2042 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2045 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2046 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
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);
2050 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2051 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2052 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2055 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2057 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2058 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2060 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2061 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2063 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2064 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2067 switch (buffer_format->justification)
2069 case GTK_JUSTIFY_LEFT:
2070 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2072 case GTK_JUSTIFY_CENTER:
2073 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2075 case GTK_JUSTIFY_RIGHT:
2076 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2083 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2085 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2086 G_CALLBACK (modest_msg_edit_window_color_button_change),
2088 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2089 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2090 G_CALLBACK (modest_msg_edit_window_color_button_change),
2093 if (priv->current_size_index != buffer_format->font_size) {
2097 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2098 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2102 priv->current_size_index = buffer_format->font_size;
2104 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2105 markup = g_strconcat ("<span font_family='Sans'>",
2106 size_text, "</span>", NULL);
2108 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2112 gtk_tree_path_free (path);
2115 if (priv->current_face_index != buffer_format->font) {
2119 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2120 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2124 priv->current_face_index = buffer_format->font;
2125 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2126 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2127 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2134 g_free (buffer_format);
2138 #ifdef MODEST_HILDON_VERSION_0
2140 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2143 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2144 ModestMsgEditWindowPrivate *priv;
2145 GtkWidget *dialog = NULL;
2147 GdkColor *new_color = NULL;
2149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2150 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2152 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2153 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2154 g_free (buffer_format);
2156 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2157 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2158 if (new_color != NULL) {
2159 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2160 (gpointer) new_color);
2163 gtk_widget_destroy (dialog);
2168 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2171 ModestMsgEditWindowPrivate *priv;
2172 GtkWidget *dialog = NULL;
2174 GdkColor *old_color = NULL;
2175 const GdkColor *new_color = NULL;
2177 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2178 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2180 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2181 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2183 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2184 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2185 if (new_color != NULL)
2186 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2188 gtk_widget_destroy (dialog);
2194 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2197 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2198 ModestMsgEditWindowPrivate *priv;
2199 GtkWidget *dialog = NULL;
2201 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2202 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2204 dialog = hildon_color_chooser_new ();
2205 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2206 g_free (buffer_format);
2208 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2210 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2211 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2214 gtk_widget_destroy (dialog);
2219 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2222 ModestMsgEditWindowPrivate *priv;
2223 GtkWidget *dialog = NULL;
2224 GdkColor *old_color = NULL;
2226 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2227 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2229 dialog = hildon_color_chooser_new ();
2230 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2232 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2234 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2235 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2237 gtk_widget_destroy (dialog);
2240 #endif /*!MODEST_HILDON_VERSION_0*/
2245 create_stream_for_uri (const gchar* uri)
2250 TnyStream *result = NULL;
2252 GnomeVFSHandle *handle = NULL;
2253 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2254 if (test == GNOME_VFS_OK) {
2255 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2256 /* Streams over OBEX (Bluetooth) are not seekable but
2257 * we expect them to be (we might need to read them
2258 * several times). So if this is a Bluetooth URI just
2259 * read the whole file into memory (this is not a fast
2260 * protocol so we can assume that these files are not
2261 * going to be very big) */
2262 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2263 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2264 TnyStream *memstream = tny_camel_mem_stream_new ();
2265 tny_stream_write_to_stream (vfssstream, memstream);
2266 g_object_unref (vfssstream);
2269 result = vfssstream;
2277 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2280 ModestMsgEditWindowPrivate *priv;
2281 GtkWidget *dialog = NULL;
2283 GSList *uris = NULL;
2284 GSList *uri_node = NULL;
2286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2289 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2290 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2292 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2294 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2295 GTK_WINDOW (dialog), GTK_WINDOW (window));
2297 response = gtk_dialog_run (GTK_DIALOG (dialog));
2299 case GTK_RESPONSE_OK:
2301 gchar *current_folder;
2302 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2303 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2304 if (current_folder && current_folder != '\0') {
2306 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2307 current_folder, &err);
2309 g_debug ("Error storing latest used folder: %s", err->message);
2313 g_free (current_folder);
2319 gtk_widget_destroy (dialog);
2321 g_object_ref (window);
2322 /* The operation could take some time so allow the dialog to be closed */
2323 while (gtk_events_pending ())
2324 gtk_main_iteration ();
2326 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2328 GnomeVFSHandle *handle = NULL;
2329 GnomeVFSResult result;
2330 GtkTextIter position;
2331 GtkTextMark *insert_mark;
2333 uri = (const gchar *) uri_node->data;
2334 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2335 if (result == GNOME_VFS_OK) {
2337 GnomeVFSFileInfo *info;
2338 gchar *filename, *basename, *escaped_filename;
2339 TnyMimePart *mime_part;
2341 const gchar *mime_type = NULL;
2342 GnomeVFSURI *vfs_uri;
2343 guint64 stream_size;
2345 gnome_vfs_close (handle);
2346 vfs_uri = gnome_vfs_uri_new (uri);
2348 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2349 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2350 g_free (escaped_filename);
2351 gnome_vfs_uri_unref (vfs_uri);
2352 info = gnome_vfs_file_info_new ();
2354 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2355 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2357 mime_type = gnome_vfs_file_info_get_mime_type (info);
2359 mime_part = tny_platform_factory_new_mime_part
2360 (modest_runtime_get_platform_factory ());
2362 TnyStream *stream = create_stream_for_uri (uri);
2364 if (stream == NULL) {
2366 modest_platform_information_banner (NULL, NULL,
2367 _FM("sfil_ib_opening_not_allowed"));
2369 g_object_unref (mime_part);
2370 gnome_vfs_file_info_unref (info);
2374 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2376 content_id = g_strdup_printf ("%d", priv->next_cid);
2377 tny_mime_part_set_content_id (mime_part, content_id);
2378 g_free (content_id);
2381 basename = g_path_get_basename (filename);
2382 tny_mime_part_set_filename (mime_part, basename);
2385 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2387 if (pixbuf != NULL) {
2388 priv->images_size += stream_size;
2389 priv->images_count ++;
2390 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2391 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2392 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2393 tny_mime_part_get_content_id (mime_part), pixbuf);
2394 g_object_unref (pixbuf);
2396 tny_list_prepend (priv->images, (GObject *) mime_part);
2397 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2399 modest_platform_information_banner (NULL, NULL,
2400 _("mail_ib_file_operation_failed"));
2404 g_object_unref (mime_part);
2405 gnome_vfs_file_info_unref (info);
2409 g_object_unref (window);
2413 on_attach_file_response (GtkDialog *dialog,
2417 GSList *uris = NULL;
2419 GnomeVFSFileSize total_size, allowed_size;
2420 ModestMsgEditWindow *window;
2421 ModestMsgEditWindowPrivate *priv;
2426 case GTK_RESPONSE_OK:
2428 gchar *current_folder;
2430 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2431 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2432 if (current_folder && current_folder != '\0') {
2434 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2435 current_folder, &err);
2437 g_debug ("Error storing latest used folder: %s", err->message);
2441 g_free (current_folder);
2448 window = MODEST_MSG_EDIT_WINDOW (user_data);
2449 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2451 /* allowed size is the maximum size - what's already there */
2452 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2453 &att_num, &att_size);
2454 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2457 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2459 const gchar *uri = (const gchar *) uri_node->data;
2462 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2464 if (total_size > allowed_size) {
2465 g_warning ("%s: total size: %u",
2466 __FUNCTION__, (unsigned int)total_size);
2469 allowed_size -= total_size;
2471 g_slist_foreach (uris, (GFunc) g_free, NULL);
2472 g_slist_free (uris);
2474 gtk_widget_destroy (GTK_WIDGET (dialog));
2478 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2480 GtkWidget *dialog = NULL;
2481 ModestMsgEditWindowPrivate *priv;
2484 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2488 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2491 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2492 GTK_FILE_CHOOSER_ACTION_OPEN);
2493 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2494 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2495 if (conf_folder && conf_folder[0] != '\0') {
2496 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2499 /* Set the default folder to images folder */
2500 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2501 ".documents", NULL);
2502 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2503 g_free (docs_folder);
2505 g_free (conf_folder);
2506 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2507 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2508 GTK_WINDOW (dialog), GTK_WINDOW (window));
2510 /* Connect to response & show */
2511 g_signal_connect (dialog, "response",
2512 G_CALLBACK (on_attach_file_response), window);
2513 gtk_widget_show (dialog);
2518 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2520 GnomeVFSFileSize allowed_size)
2523 GnomeVFSHandle *handle = NULL;
2524 ModestMsgEditWindowPrivate *priv;
2525 GnomeVFSResult result;
2526 GnomeVFSFileSize size = 0;
2527 g_return_val_if_fail (window, 0);
2528 g_return_val_if_fail (uri, 0);
2530 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2532 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2533 if (result == GNOME_VFS_OK) {
2534 TnyMimePart *mime_part;
2536 const gchar *mime_type = NULL;
2538 gchar *escaped_filename;
2541 GnomeVFSFileInfo *info;
2542 GnomeVFSURI *vfs_uri;
2544 gnome_vfs_close (handle);
2545 vfs_uri = gnome_vfs_uri_new (uri);
2548 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2549 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2550 g_free (escaped_filename);
2551 gnome_vfs_uri_unref (vfs_uri);
2553 info = gnome_vfs_file_info_new ();
2555 if (gnome_vfs_get_file_info (uri,
2557 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2559 mime_type = gnome_vfs_file_info_get_mime_type (info);
2560 mime_part = tny_platform_factory_new_mime_part
2561 (modest_runtime_get_platform_factory ());
2563 /* try to get the attachment's size; this may fail for weird
2564 * file systems, like obex, upnp... */
2565 if (allowed_size != 0 &&
2566 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2568 if (size > allowed_size) {
2569 modest_platform_information_banner (NULL, NULL,
2570 _FM("sfil_ib_opening_not_allowed"));
2575 g_warning ("%s: could not get attachment size", __FUNCTION__);
2577 stream = create_stream_for_uri (uri);
2579 if (stream == NULL) {
2581 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2583 g_object_unref (mime_part);
2585 gnome_vfs_file_info_unref (info);
2589 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2590 g_object_unref (stream);
2592 content_id = g_strdup_printf ("%d", priv->next_cid);
2593 tny_mime_part_set_content_id (mime_part, content_id);
2594 g_free (content_id);
2597 basename = g_path_get_basename (filename);
2598 tny_mime_part_set_filename (mime_part, basename);
2601 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2602 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2604 info->size == 0, info->size);
2605 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2606 gtk_widget_show_all (priv->attachments_caption);
2607 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2609 g_object_unref (mime_part);
2610 gnome_vfs_file_info_unref (info);
2617 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2620 ModestMsgEditWindowPrivate *priv;
2623 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2626 if (att_list == NULL) {
2627 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2628 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2629 g_object_unref (att_list);
2634 g_object_ref (att_list);
2637 if (tny_list_get_length (att_list) == 0) {
2638 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2640 gboolean dialog_response;
2641 gchar *message = NULL;
2642 gchar *filename = NULL;
2644 if (tny_list_get_length (att_list) == 1) {
2646 iter = tny_list_create_iterator (att_list);
2647 part = (TnyMimePart *) tny_iterator_get_current (iter);
2648 g_object_unref (iter);
2649 if (TNY_IS_MSG (part)) {
2650 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2652 filename = tny_header_dup_subject (header);
2653 g_object_unref (header);
2655 if (filename == NULL) {
2656 filename = g_strdup (_("mail_va_no_subject"));
2659 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2661 g_object_unref (part);
2663 filename = g_strdup ("");
2665 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2666 "emev_nc_delete_attachments",
2667 tny_list_get_length (att_list)), filename);
2670 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2674 if (dialog_response != GTK_RESPONSE_OK) {
2675 g_object_unref (att_list);
2679 for (iter = tny_list_create_iterator (att_list);
2680 !tny_iterator_is_done (iter);
2681 tny_iterator_next (iter)) {
2682 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2683 const gchar *att_id;
2684 tny_list_remove (priv->attachments, (GObject *) mime_part);
2686 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2688 if (tny_list_get_length (priv->attachments) == 0)
2689 gtk_widget_hide (priv->attachments_caption);
2690 att_id = tny_mime_part_get_content_id (mime_part);
2692 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2694 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2695 g_object_unref (mime_part);
2697 g_object_unref (iter);
2700 g_object_unref (att_list);
2702 /* if the last attachment has been removed, focus the Subject: field */
2703 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2704 gtk_widget_grab_focus (priv->subject_field);
2708 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2711 ModestMsgEditWindowPrivate *priv;
2712 GdkColor *new_color;
2713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2715 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2716 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2719 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2721 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2723 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2725 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2730 font_size_clicked (GtkToolButton *button,
2731 ModestMsgEditWindow *window)
2733 ModestMsgEditWindowPrivate *priv;
2734 GtkWidget *selector, *dialog;
2736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2738 selector = hildon_touch_selector_new ();
2739 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2740 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2742 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2743 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2744 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2746 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2750 WPTextBufferFormat format;
2752 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2754 memset (&format, 0, sizeof (format));
2755 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2757 format.cs.font_size = TRUE;
2758 format.cs.text_position = TRUE;
2759 format.cs.font = TRUE;
2760 format.font_size = new_index;
2761 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2763 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2764 GINT_TO_POINTER (new_index)))
2765 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2767 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2768 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2769 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2770 size_text, "</span>", NULL);
2772 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2776 gtk_widget_destroy (dialog);
2778 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2783 font_face_clicked (GtkToolButton *button,
2784 ModestMsgEditWindow *window)
2786 ModestMsgEditWindowPrivate *priv;
2787 GtkWidget *selector, *dialog;
2788 GtkCellRenderer *renderer;
2790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2792 selector = hildon_touch_selector_new ();
2793 renderer = gtk_cell_renderer_text_new ();
2794 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2795 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2796 renderer, "family", 0, "text", 0, NULL);
2797 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2799 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2800 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2801 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2803 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2804 gint new_font_index;
2808 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2809 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2810 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2814 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2816 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2817 GINT_TO_POINTER(new_font_index)))
2818 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2820 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2821 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2823 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2827 gtk_tree_path_free (path);
2830 gtk_widget_destroy (dialog);
2832 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2837 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2840 ModestMsgEditWindowPrivate *priv = NULL;
2841 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2843 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2844 if (!priv->update_caption_visibility)
2847 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2849 gtk_widget_show (priv->cc_caption);
2851 gtk_widget_hide (priv->cc_caption);
2853 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2857 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2860 ModestMsgEditWindowPrivate *priv = NULL;
2861 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2863 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2864 if (!priv->update_caption_visibility)
2867 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2869 gtk_widget_show (priv->bcc_caption);
2871 gtk_widget_hide (priv->bcc_caption);
2873 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2877 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2878 ModestRecptEditor *editor)
2880 ModestMsgEditWindowPrivate *priv;
2882 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2883 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2885 /* we check for low-mem; in that case, show a warning, and don't allow
2886 * for the addressbook
2888 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2891 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2893 if (editor == NULL) {
2894 GtkWidget *view_focus;
2895 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2897 /* This code should be kept in sync with ModestRecptEditor. The
2898 textview inside the recpt editor is the one that really gets the
2899 focus. As it's inside a scrolled window, and this one inside the
2900 hbox recpt editor inherits from, we'll need to go up in the
2901 hierarchy to know if the text view is part of the recpt editor
2902 or if it's a different text entry */
2904 if (gtk_widget_get_parent (view_focus)) {
2905 GtkWidget *first_parent;
2907 first_parent = gtk_widget_get_parent (view_focus);
2908 if (gtk_widget_get_parent (first_parent) &&
2909 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2910 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2915 editor = MODEST_RECPT_EDITOR (priv->to_field);
2919 modest_address_book_select_addresses (editor);
2924 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2926 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2928 modest_msg_edit_window_open_addressbook (window, NULL);
2932 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2933 gboolean show_toolbar)
2935 ModestWindowPrivate *parent_priv;
2937 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2938 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2940 /* We can not just use the code of
2941 modest_msg_edit_window_setup_toolbar because it has a
2942 mixture of both initialization and creation code. */
2944 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2946 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2950 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2951 TnyHeaderFlags priority_flags)
2953 ModestMsgEditWindowPrivate *priv;
2954 ModestWindowPrivate *parent_priv;
2956 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2961 if (priv->priority_flags != priority_flags) {
2962 GtkAction *priority_action = NULL;
2964 priv->priority_flags = priority_flags;
2966 switch (priority_flags) {
2967 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2968 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2969 MODEST_HEADER_ICON_HIGH,
2970 HILDON_ICON_SIZE_SMALL);
2971 gtk_widget_show (priv->priority_icon);
2972 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2973 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2975 case TNY_HEADER_FLAG_LOW_PRIORITY:
2976 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2977 MODEST_HEADER_ICON_LOW,
2978 HILDON_ICON_SIZE_SMALL);
2979 gtk_widget_show (priv->priority_icon);
2980 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2981 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2984 gtk_widget_hide (priv->priority_icon);
2985 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2986 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2989 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2990 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2992 gtk_widget_queue_resize (priv->subject_box);
2996 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2999 ModestMsgEditWindowPrivate *priv;
3000 ModestWindowPrivate *parent_priv;
3001 gint current_format;
3003 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3005 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3006 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3008 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3009 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3011 if (current_format != file_format) {
3012 switch (file_format) {
3013 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3014 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3015 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3017 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3021 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3022 response = gtk_dialog_run (GTK_DIALOG (dialog));
3023 gtk_widget_destroy (dialog);
3024 if (response == GTK_RESPONSE_OK) {
3025 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3027 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3028 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3033 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3034 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3035 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3040 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3043 ModestMsgEditWindowPrivate *priv;
3044 WPTextBufferFormat oldfmt, fmt;
3045 gint old_position = 0;
3049 GdkColor *color = NULL;
3050 gboolean bold, bold_set, italic, italic_set;
3051 gboolean underline, underline_set;
3052 gboolean strikethrough, strikethrough_set;
3053 gboolean position_set;
3054 gboolean font_size_set, font_set, color_set;
3057 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3060 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3061 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3062 GTK_WINDOW(dialog), GTK_WINDOW (window));
3064 /* First we get the currently selected font information */
3065 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3067 switch (oldfmt.text_position) {
3068 case TEXT_POSITION_NORMAL:
3071 case TEXT_POSITION_SUPERSCRIPT:
3079 g_object_set (G_OBJECT (dialog),
3080 "bold", oldfmt.bold != FALSE,
3081 "bold-set", !oldfmt.cs.bold,
3082 "underline", oldfmt.underline != FALSE,
3083 "underline-set", !oldfmt.cs.underline,
3084 "italic", oldfmt.italic != FALSE,
3085 "italic-set", !oldfmt.cs.italic,
3086 "strikethrough", oldfmt.strikethrough != FALSE,
3087 "strikethrough-set", !oldfmt.cs.strikethrough,
3088 "color", &oldfmt.color,
3089 "color-set", !oldfmt.cs.color,
3090 "size", wp_font_size[oldfmt.font_size],
3091 "size-set", !oldfmt.cs.font_size,
3092 "position", old_position,
3093 "position-set", !oldfmt.cs.text_position,
3094 "family", wp_get_font_name (oldfmt.font),
3095 "family-set", !oldfmt.cs.font,
3098 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3099 GTK_WINDOW (dialog), GTK_WINDOW (window));
3100 gtk_widget_show_all (dialog);
3101 priv->font_dialog = dialog;
3102 response = gtk_dialog_run (GTK_DIALOG (dialog));
3103 priv->font_dialog = NULL;
3104 if (response == GTK_RESPONSE_OK) {
3106 g_object_get( dialog,
3108 "bold-set", &bold_set,
3109 "underline", &underline,
3110 "underline-set", &underline_set,
3112 "italic-set", &italic_set,
3113 "strikethrough", &strikethrough,
3114 "strikethrough-set", &strikethrough_set,
3116 "color-set", &color_set,
3118 "size-set", &font_size_set,
3119 "family", &font_name,
3120 "family-set", &font_set,
3121 "position", &position,
3122 "position-set", &position_set,
3127 if (response == GTK_RESPONSE_OK) {
3128 memset(&fmt, 0, sizeof(fmt));
3134 fmt.italic = italic;
3135 fmt.cs.italic = TRUE;
3137 if (underline_set) {
3138 fmt.underline = underline;
3139 fmt.cs.underline = TRUE;
3141 if (strikethrough_set) {
3142 fmt.strikethrough = strikethrough;
3143 fmt.cs.strikethrough = TRUE;
3148 ? TEXT_POSITION_NORMAL
3149 : ( ( position == 1 )
3150 ? TEXT_POSITION_SUPERSCRIPT
3151 : TEXT_POSITION_SUBSCRIPT );
3152 fmt.cs.text_position = TRUE;
3153 fmt.font_size = oldfmt.font_size;
3157 fmt.cs.color = TRUE;
3160 fmt.font = wp_get_font_index(font_name,
3165 if (font_size_set) {
3166 fmt.cs.font_size = TRUE;
3167 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3169 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3170 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3172 gtk_widget_destroy (dialog);
3174 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3178 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3180 ModestMsgEditWindowPrivate *priv;
3182 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3183 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3185 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3187 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3188 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3192 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3194 ModestMsgEditWindowPrivate *priv;
3196 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3199 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3201 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3202 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3207 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3209 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3211 priv->can_undo = can_undo;
3215 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3217 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3219 priv->can_redo = can_redo;
3223 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3225 ModestMsgEditWindowPrivate *priv;
3226 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3227 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3229 return priv->can_undo;
3233 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3235 ModestMsgEditWindowPrivate *priv;
3236 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3237 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3239 return priv->can_redo;
3244 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3247 GtkTextIter match_start, match_end;
3249 if (image_id == NULL)
3252 gtk_text_buffer_get_start_iter (buffer, &iter);
3254 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3255 GSList *tags = gtk_text_iter_get_tags (&match_start);
3257 for (node = tags; node != NULL; node = g_slist_next (node)) {
3258 GtkTextTag *tag = (GtkTextTag *) node->data;
3259 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3260 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3261 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3263 offset = gtk_text_iter_get_offset (&match_start);
3264 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3265 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3269 gtk_text_iter_forward_char (&iter);
3274 message_is_empty (ModestMsgEditWindow *window)
3276 ModestMsgEditWindowPrivate *priv = NULL;
3278 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3279 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3281 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3282 * so we can ignore markup.
3284 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3287 count = gtk_text_buffer_get_char_count (buf);
3293 msg_body_focus (GtkWidget *focus,
3294 GdkEventFocus *event,
3298 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3299 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3300 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3305 recpt_field_changed (GtkTextBuffer *buffer,
3306 ModestMsgEditWindow *editor)
3308 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3309 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3313 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3315 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3316 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3320 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3323 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3324 GtkTextBuffer *buffer;
3326 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3327 gtk_text_buffer_set_modified (buffer, modified);
3328 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3329 gtk_text_buffer_set_modified (buffer, modified);
3330 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3331 gtk_text_buffer_set_modified (buffer, modified);
3332 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3336 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3338 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3339 const char *account_name;
3340 GtkTextBuffer *buffer;
3342 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3343 if (gtk_text_buffer_get_modified (buffer))
3345 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3346 if (gtk_text_buffer_get_modified (buffer))
3348 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3349 if (gtk_text_buffer_get_modified (buffer))
3351 if (gtk_text_buffer_get_modified (priv->text_buffer))
3354 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3355 if (priv->original_mailbox) {
3356 if (!account_name || strcmp (account_name, priv->original_mailbox))
3358 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3369 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3371 ModestMsgEditWindowPrivate *priv = NULL;
3373 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3374 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3376 /* check if there's no recipient added */
3377 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3378 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3379 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3380 /* no recipient contents, then select contacts */
3381 modest_msg_edit_window_open_addressbook (window, NULL);
3385 g_object_ref (window);
3386 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3387 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3388 g_object_unref (window);
3391 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3392 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3393 g_object_unref (window);
3396 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3397 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3398 g_object_unref (window);
3402 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3403 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3404 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3405 g_object_unref (window);
3412 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3413 ModestMsgEditWindow *window)
3415 modest_msg_edit_window_offer_attach_file (window);
3419 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3421 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3423 return priv->clipboard_text;
3427 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3429 ModestMsgEditWindow *window)
3431 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3432 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3435 /* It could happen that the window was already closed */
3436 if (!GTK_WIDGET_VISIBLE (window))
3439 g_object_ref (window);
3440 text = gtk_clipboard_wait_for_text (selection_clipboard);
3442 if (priv->clipboard_text != NULL) {
3443 g_free (priv->clipboard_text);
3445 priv->clipboard_text = text;
3447 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3449 g_object_unref (window);
3452 static gboolean clipboard_owner_change_idle (gpointer userdata)
3454 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3455 ModestMsgEditWindowPrivate *priv;
3457 gdk_threads_enter ();
3458 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3459 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3461 priv->clipboard_owner_idle = 0;
3462 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3463 gdk_threads_leave ();
3469 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3471 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3472 if (priv->clipboard_owner_idle == 0) {
3473 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3474 clipboard_owner_change_idle,
3475 g_object_ref (window),
3481 subject_field_move_cursor (GtkEntry *entry,
3482 GtkMovementStep step,
3487 /* It could happen that the window was already closed */
3488 if (!GTK_WIDGET_VISIBLE (window))
3491 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3495 update_window_title (ModestMsgEditWindow *window)
3497 ModestMsgEditWindowPrivate *priv = NULL;
3498 const gchar *subject;
3500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3501 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3502 if (subject == NULL || subject[0] == '\0')
3503 subject = _("mail_va_new_email");
3505 gtk_window_set_title (GTK_WINDOW (window), subject);
3511 body_insert_text (GtkTextBuffer *buffer,
3512 GtkTextIter *location,
3515 ModestMsgEditWindow *window)
3517 GtkTextIter end_iter;
3520 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3522 offset = gtk_text_iter_get_offset (&end_iter);
3524 if (offset + len > MAX_BODY_LENGTH) {
3525 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3526 if (offset < MAX_BODY_LENGTH)
3530 /* Prevent endless recursion */
3531 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3532 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3533 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3534 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3536 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3540 if (offset + len > MAX_BODY_LENGTH) {
3541 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3542 _CS("ckdg_ib_maximum_characters_reached"));
3547 subject_field_changed (GtkEditable *editable,
3548 ModestMsgEditWindow *window)
3550 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3551 update_window_title (window);
3552 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3553 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3554 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3557 subject_field_insert_text (GtkEditable *editable,
3559 gint new_text_length,
3561 ModestMsgEditWindow *window)
3563 GString *result = g_string_new ("");
3565 gint result_len = 0;
3566 const gchar *entry_text = NULL;
3569 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3570 old_length = g_utf8_strlen (entry_text, -1);
3572 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3573 gunichar c = g_utf8_get_char_validated (current, 8);
3574 /* Invalid unichar, stop */
3580 result = g_string_append_unichar (result, c);
3584 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3585 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3588 /* Prevent endless recursion */
3589 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3590 g_signal_emit_by_name (editable, "insert-text",
3591 (gpointer) result->str, (gpointer) result->len,
3592 (gpointer) position, (gpointer) window);
3593 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3597 if (result_len + old_length > 1000) {
3598 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3599 _CS("ckdg_ib_maximum_characters_reached"));
3601 g_string_free (result, TRUE);
3605 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3608 ModestMsgEditWindowPrivate *priv = NULL;
3610 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3613 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3616 gtk_widget_show_all (priv->find_toolbar);
3617 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3619 gtk_widget_hide_all (priv->find_toolbar);
3620 gtk_widget_grab_focus (priv->msg_body);
3625 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3627 GtkTextIter *match_start,
3628 GtkTextIter *match_end)
3630 GtkTextIter end_iter;
3631 gchar *str_casefold;
3634 gchar *range_casefold;
3637 gboolean result = FALSE;
3644 gtk_text_iter_forward_to_end (&end_iter);
3646 str_casefold = g_utf8_casefold (str, -1);
3647 str_chars_n = strlen (str);
3649 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3650 range_casefold = g_utf8_casefold (range_text, -1);
3651 range_chars_n = strlen (range_casefold);
3653 if (range_chars_n < str_chars_n) {
3654 g_free (str_casefold);
3655 g_free (range_text);
3656 g_free (range_casefold);
3660 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3661 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3662 if (!g_utf8_collate (range_subtext, str_casefold)) {
3663 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3665 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3666 match_start, match_end, NULL)) {
3667 g_warning ("Matched string with collate, but not matched in model");
3669 g_free (found_text);
3671 g_free (range_subtext);
3675 g_free (str_casefold);
3676 g_free (range_text);
3677 g_free (range_casefold);
3684 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3685 ModestMsgEditWindow *window)
3687 gchar *current_search = NULL;
3688 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3690 GtkTextIter selection_start, selection_end;
3691 GtkTextIter match_start, match_end;
3692 gboolean continue_search = FALSE;
3694 if (message_is_empty (window)) {
3695 g_free (priv->last_search);
3696 priv->last_search = NULL;
3697 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3701 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3702 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3703 g_free (current_search);
3704 g_free (priv->last_search);
3705 priv->last_search = NULL;
3706 /* Information banner about empty search */
3707 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3711 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3712 continue_search = TRUE;
3714 g_free (priv->last_search);
3715 priv->last_search = g_strdup (current_search);
3718 if (continue_search) {
3719 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3720 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3721 &match_start, &match_end);
3723 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3725 GtkTextIter buffer_start;
3726 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3727 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3728 &match_start, &match_end);
3730 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3733 /* Mark as selected the string found in search */
3735 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3736 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3737 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3739 g_free (priv->last_search);
3740 priv->last_search = NULL;
3742 g_free (current_search);
3746 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3748 ModestMsgEditWindowPrivate *priv;
3750 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3755 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3758 ModestMsgEditWindowPrivate *priv;
3760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3765 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3766 ModestMsgEditWindow *window)
3768 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3772 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3775 ModestMsgEditWindowPrivate *priv;
3776 TnyHeader *header = NULL;
3778 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3779 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3783 if (priv->draft_msg != NULL) {
3784 g_object_unref (priv->draft_msg);
3787 if (draft != NULL) {
3788 g_object_ref (draft);
3789 header = tny_msg_get_header (draft);
3790 if (priv->msg_uid) {
3791 g_free (priv->msg_uid);
3792 priv->msg_uid = NULL;
3794 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3797 priv->draft_msg = draft;
3801 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3802 GtkTextIter *start, GtkTextIter *end,
3805 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3806 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3809 if (tag == NULL) return;
3810 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3811 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3812 replace_with_images (window, priv->images);
3817 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3820 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3822 g_return_if_fail (TNY_IS_MIME_PART (part));
3823 tny_list_prepend (priv->attachments, (GObject *) part);
3824 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3825 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3826 gtk_widget_show_all (priv->attachments_caption);
3827 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3831 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3833 ModestMsgEditWindowPrivate *priv;
3835 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3838 return priv->msg_uid;
3842 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3843 ModestMsgEditWindowWidgetType widget_type)
3845 ModestMsgEditWindowPrivate *priv;
3847 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3848 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3850 switch (widget_type) {
3851 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3852 return priv->msg_body;
3854 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3855 return priv->to_field;
3857 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3858 return priv->cc_field;
3860 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3861 return priv->bcc_field;
3863 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3864 return priv->subject_field;
3866 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3867 return priv->attachments_view;
3875 remove_tags (WPTextBuffer *buffer)
3877 GtkTextIter start, end;
3879 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3880 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3882 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3886 on_account_removed (TnyAccountStore *account_store,
3887 TnyAccount *account,
3890 /* Do nothing if it's a store account, because we use the
3891 transport to send the messages */
3892 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3893 const gchar *parent_acc = NULL;
3894 const gchar *our_acc = NULL;
3896 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3897 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3898 /* Close this window if I'm showing a message of the removed account */
3899 if (strcmp (parent_acc, our_acc) == 0)
3900 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3904 static void update_signature (ModestMsgEditWindow *self,
3905 const gchar *old_account,
3906 const gchar *new_account)
3908 ModestMsgEditWindowPrivate *priv;
3909 gboolean has_old_signature, has_new_signature;
3911 GtkTextIter match_start, match_end;
3912 ModestAccountMgr *mgr;
3914 gchar *full_signature;
3916 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3918 gtk_text_buffer_begin_user_action (priv->text_buffer);
3920 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3921 mgr = modest_runtime_get_account_mgr ();
3925 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3926 if (has_old_signature) {
3927 full_signature = g_strconcat ("\n--\n", signature, NULL);
3928 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3929 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3931 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3932 &match_start, &match_end, NULL)) {
3935 g_free (full_signature);
3940 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3941 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3942 if (has_new_signature) {
3943 full_signature = g_strconcat ("\n--\n", signature, NULL);
3944 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3945 g_free (full_signature);
3948 gtk_text_buffer_end_user_action (priv->text_buffer);
3952 from_field_changed (HildonPickerButton *button,
3953 ModestMsgEditWindow *self)
3955 ModestMsgEditWindowPrivate *priv;
3956 gchar *old_account, *new_account;
3958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3960 old_account = priv->last_from_account;
3961 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3962 new_account = priv->last_from_account;
3964 update_signature (self, old_account, new_account);
3968 typedef struct _MessageSettingsHelper {
3969 ModestMsgEditWindow *window;
3970 GSList *priority_group;
3971 GSList *format_group;
3972 GtkToggleButton *current_priority;
3973 GtkToggleButton *current_format;
3974 } MessageSettingsHelper;
3977 on_priority_toggle (GtkToggleButton *button,
3978 MessageSettingsHelper *helper)
3981 ModestMsgEditWindowPrivate *priv;
3983 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3984 if (gtk_toggle_button_get_active (button)) {
3986 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3987 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3988 if ((node_button != button) &&
3989 gtk_toggle_button_get_active (node_button)) {
3990 gtk_toggle_button_set_active (node_button, FALSE);
3993 helper->current_priority = button;
3995 gboolean found = FALSE;
3996 /* If no one is active, activate it again */
3997 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3998 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3999 if (gtk_toggle_button_get_active (node_button)) {
4005 gtk_toggle_button_set_active (button, TRUE);
4011 on_format_toggle (GtkToggleButton *button,
4012 MessageSettingsHelper *helper)
4015 ModestMsgEditWindowPrivate *priv;
4017 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4018 if (gtk_toggle_button_get_active (button)) {
4020 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4021 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4022 if ((node_button != button) &&
4023 gtk_toggle_button_get_active (node_button)) {
4024 gtk_toggle_button_set_active (node_button, FALSE);
4027 helper->current_format = button;
4029 gboolean found = FALSE;
4030 /* If no one is active, activate it again */
4031 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4032 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4033 if (gtk_toggle_button_get_active (node_button)) {
4039 gtk_toggle_button_set_active (button, TRUE);
4046 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4051 GtkWidget *priority_hbox;
4052 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4053 GtkWidget *captioned;
4054 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4055 GtkWidget *format_hbox;
4056 GtkWidget *html_toggle, *text_toggle;
4057 ModestMsgEditWindowPrivate *priv;
4058 MessageSettingsHelper helper = {0,};
4060 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4061 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4062 helper.window = window;
4063 helper.priority_group = NULL;
4064 helper.format_group = NULL;
4066 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4067 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4069 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4070 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4071 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4072 vbox = gtk_vbox_new (FALSE, 0);
4073 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4074 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4075 gtk_container_add (GTK_CONTAINER (align), vbox);
4076 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4077 gtk_widget_show (align);
4078 gtk_widget_show (vbox);
4080 /* Priority toggles */
4081 priority_hbox = gtk_hbox_new (TRUE, 0);
4082 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4083 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4084 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4085 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4086 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4087 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4088 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4089 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4090 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4091 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4092 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4093 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4094 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4095 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4096 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4097 gtk_widget_show_all (priority_hbox);
4098 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4099 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4100 gtk_widget_show (captioned);
4101 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4103 /* format toggles */
4104 format_hbox = gtk_hbox_new (TRUE, 0);
4105 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4106 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4107 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4108 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4109 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4110 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4111 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4112 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4113 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4114 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4115 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4116 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4117 gtk_widget_show_all (format_hbox);
4118 gtk_widget_show (format_hbox);
4119 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4122 g_object_unref (title_sizegroup);
4123 g_object_unref (value_sizegroup);
4125 /* Set current values */
4126 switch (priv->priority_flags) {
4127 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4128 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4129 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4131 case TNY_HEADER_FLAG_LOW_PRIORITY:
4132 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4133 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4136 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4137 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4141 switch (modest_msg_edit_window_get_format (window)) {
4142 case MODEST_MSG_EDIT_FORMAT_TEXT:
4143 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4144 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4146 case MODEST_MSG_EDIT_FORMAT_HTML:
4148 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4149 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4153 /* Signal connects */
4154 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4155 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4156 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4157 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4158 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4160 /* Save settings if the user clicked on done */
4161 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4162 TnyHeaderFlags flags;
4163 ModestMsgEditFormat old_format, new_format;
4165 /* Set priority flags */
4166 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4167 if (priv->priority_flags != flags)
4168 modest_msg_edit_window_set_priority_flags (window, flags);
4170 /* Set edit format */
4171 old_format = modest_msg_edit_window_get_format (window);
4172 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4173 if (old_format != new_format) {
4174 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4175 modest_msg_edit_window_set_file_format (window, file_format);
4179 gtk_widget_destroy (dialog);
4180 g_slist_free (helper.priority_group);
4184 on_message_settings (GtkAction *action,
4185 ModestMsgEditWindow *window)
4187 modest_msg_edit_window_show_msg_settings_dialog (window);
4191 on_cc_button_toggled (HildonCheckButton *button,
4192 ModestMsgEditWindow *window)
4194 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4196 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4197 hildon_check_button_get_active (button));
4201 on_bcc_button_toggled (HildonCheckButton *button,
4202 ModestMsgEditWindow *window)
4204 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4206 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4207 hildon_check_button_get_active (button));
4211 setup_menu (ModestMsgEditWindow *self)
4213 ModestMsgEditWindowPrivate *priv = NULL;
4215 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4217 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4219 /* Settings menu buttons */
4220 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4221 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4223 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4224 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4225 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4227 priv->cc_button = hildon_check_button_new (0);
4228 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4229 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4231 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4233 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4234 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4235 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4236 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4238 priv->bcc_button = hildon_check_button_new (0);
4239 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4240 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4242 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4244 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4245 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4246 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4247 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4249 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4250 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4251 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4252 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: add attachment"), NULL,
4253 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4255 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4256 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4257 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4258 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4259 APP_MENU_CALLBACK (on_message_settings),
4261 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4262 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4267 emit_open_addressbook (GtkButton *button,
4268 ModestRecptEditor *editor)
4270 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4274 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4275 const gchar *label, GtkWidget *control)
4277 GtkWidget *abook_button;
4281 box = gtk_hbox_new (FALSE, 0);
4283 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4284 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4286 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4287 gtk_button_set_label (GTK_BUTTON (abook_button), label);
4289 gtk_container_add (GTK_CONTAINER (align), abook_button);
4290 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4291 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4292 if (title_size_group)
4293 gtk_size_group_add_widget (title_size_group, abook_button);
4294 if (value_size_group)
4295 gtk_size_group_add_widget (value_size_group, control);
4297 g_signal_connect (G_OBJECT (abook_button), "clicked",
4298 G_CALLBACK (emit_open_addressbook), control);