1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
191 const gchar *label, GtkWidget *control);
192 static void DEBUG_BUFFER (WPTextBuffer *buffer)
196 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
198 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
199 while (!gtk_text_iter_is_end (&iter)) {
200 GString *output = g_string_new ("");
201 GSList *toggled_tags;
204 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
205 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
206 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
207 GtkTextTag *tag = (GtkTextTag *) node->data;
209 g_object_get (G_OBJECT (tag), "name", &name, NULL);
210 output = g_string_append (output, name);
211 g_string_append (output, " ");
213 output = g_string_append (output, "] OPENED [ ");
214 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
215 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
216 GtkTextTag *tag = (GtkTextTag *) node->data;
218 g_object_get (G_OBJECT (tag), "name", &name, NULL);
219 output = g_string_append (output, name);
220 g_string_append (output, " ");
222 output = g_string_append (output, "]\n");
223 g_message ("%s", output->str);
224 g_string_free (output, TRUE);
225 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
227 g_message ("END BUFFER");
231 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
232 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
236 /* static gboolean */
237 /* on_key_pressed (GtkWidget *self, */
238 /* GdkEventKey *event, */
239 /* gpointer user_data); */
241 /* list my signals */
248 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
249 struct _ModestMsgEditWindowPrivate {
251 GtkWidget *header_box;
253 ModestPairList *from_field_protos;
254 GtkWidget *from_field;
255 gchar *last_from_account;
256 gchar *original_account_name;
261 gchar *original_mailbox;
265 GtkWidget *bcc_field;
266 GtkWidget *subject_field;
267 GtkWidget *attachments_view;
268 GtkWidget *priority_icon;
269 GtkWidget *subject_box;
270 GtkWidget *send_button;
272 GtkWidget *cc_caption;
273 GtkWidget *bcc_caption;
274 gboolean update_caption_visibility;
275 GtkWidget *attachments_caption;
277 GtkTextBuffer *text_buffer;
279 GtkWidget *font_size_toolitem;
280 GtkWidget *font_face_toolitem;
281 GtkWidget *font_color_button;
282 GtkWidget *font_color_toolitem;
283 GSList *font_items_group;
284 GtkTreeModel *faces_model;
285 gint current_face_index;
286 GtkWidget *font_tool_button_label;
287 GtkTreeModel *sizes_model;
288 gint current_size_index;
289 GtkWidget *size_tool_button_label;
291 GtkWidget *find_toolbar;
294 GtkWidget *font_dialog;
297 guint correct_scroll_idle;
298 guint scroll_drag_timeout_id;
302 TnyList *attachments;
307 TnyHeaderFlags priority_flags;
309 gboolean can_undo, can_redo;
310 gulong clipboard_change_handler_id;
311 gulong default_clipboard_change_handler_id;
312 gulong account_removed_handler_id;
313 guint clipboard_owner_idle;
314 gchar *clipboard_text;
323 GtkWidget *cc_button;
324 GtkWidget *bcc_button;
327 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
328 MODEST_TYPE_MSG_EDIT_WINDOW, \
329 ModestMsgEditWindowPrivate))
331 static GtkWindowClass *parent_class = NULL;
333 /* uncomment the following if you have defined any signals */
334 /* static guint signals[LAST_SIGNAL] = {0}; */
337 modest_msg_edit_window_get_type (void)
339 static GType my_type = 0;
341 static const GTypeInfo my_info = {
342 sizeof(ModestMsgEditWindowClass),
343 NULL, /* base init */
344 NULL, /* base finalize */
345 (GClassInitFunc) modest_msg_edit_window_class_init,
346 NULL, /* class finalize */
347 NULL, /* class data */
348 sizeof(ModestMsgEditWindow),
350 (GInstanceInitFunc) modest_msg_edit_window_init,
353 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
354 "ModestMsgEditWindow",
362 save_state (ModestWindow *self)
364 modest_widget_memory_save (modest_runtime_get_conf(),
365 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
370 restore_settings (ModestMsgEditWindow *self)
372 ModestConf *conf = NULL;
374 conf = modest_runtime_get_conf ();
376 /* Dim at start clipboard actions */
377 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
382 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
384 GObjectClass *gobject_class;
385 ModestWindowClass *modest_window_class;
386 gobject_class = (GObjectClass*) klass;
387 modest_window_class = (ModestWindowClass*) klass;
389 parent_class = g_type_class_peek_parent (klass);
390 gobject_class->finalize = modest_msg_edit_window_finalize;
392 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
393 modest_window_class->save_state_func = save_state;
394 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
396 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
400 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
402 ModestMsgEditWindowPrivate *priv;
403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
405 priv->msg_body = NULL;
406 priv->from_field = NULL;
407 priv->to_field = NULL;
408 priv->cc_field = NULL;
409 priv->bcc_field = NULL;
410 priv->subject_field = NULL;
411 priv->attachments = TNY_LIST (tny_simple_list_new ());
412 priv->images = TNY_LIST (tny_simple_list_new ());
413 priv->images_size = 0;
414 priv->images_count = 0;
417 priv->cc_caption = NULL;
418 priv->bcc_caption = NULL;
419 priv->update_caption_visibility = FALSE;
421 priv->priority_flags = 0;
423 priv->find_toolbar = NULL;
424 priv->last_search = NULL;
426 priv->draft_msg = NULL;
427 priv->outbox_msg = NULL;
428 priv->msg_uid = NULL;
430 priv->can_undo = FALSE;
431 priv->can_redo = FALSE;
432 priv->clipboard_change_handler_id = 0;
433 priv->default_clipboard_change_handler_id = 0;
434 priv->account_removed_handler_id = 0;
435 priv->clipboard_owner_idle = 0;
436 priv->clipboard_text = NULL;
439 priv->scroll_drag_timeout_id = 0;
440 priv->correct_scroll_idle = 0;
441 priv->last_upper = 0.0;
443 priv->font_dialog = NULL;
444 priv->app_menu = NULL;
446 priv->references = NULL;
447 priv->in_reply_to = NULL;
449 if (!is_wp_text_buffer_started) {
450 is_wp_text_buffer_started = TRUE;
451 wp_text_buffer_library_init ();
456 hildon_program_add_window (hildon_program_get_instance(),
461 multimailbox_get_default_mailbox (const gchar *account_name)
463 gchar *transport_account;
464 gchar *result = NULL;
466 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
468 TNY_ACCOUNT_TYPE_TRANSPORT);
469 if (transport_account) {
471 ModestProtocolRegistry *registry;
473 registry = modest_runtime_get_protocol_registry ();
475 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
476 MODEST_ACCOUNT_PROTO, TRUE);
478 ModestProtocol *protocol =
479 modest_protocol_registry_get_protocol_by_name (registry,
480 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
482 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
483 ModestPairList *pair_list;
485 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
488 ModestPair *pair = (ModestPair *) pair_list->data;
489 result = g_strdup ((const gchar *) pair->first);
490 modest_pair_list_free (pair_list);
501 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
503 static ModestPairList*
504 get_transports (void)
506 GSList *transports = NULL;
508 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
509 GSList *accounts = modest_account_mgr_account_names (account_mgr,
510 TRUE /* only enabled accounts. */);
512 GSList *cursor = accounts;
514 gchar *account_name = cursor->data;
517 gchar *transport_account;
518 gboolean multi_mailbox = FALSE;
519 ModestProtocol *protocol = NULL;
521 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
523 transport_account = modest_account_mgr_get_server_account_name
524 (modest_runtime_get_account_mgr (),
526 TNY_ACCOUNT_TYPE_TRANSPORT);
527 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
528 ModestPairList *pair_list;
529 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
532 transports = g_slist_concat (transports, pair_list);
533 multi_mailbox = TRUE;
538 if (!multi_mailbox) {
539 gchar *from_string = NULL;
541 from_string = modest_account_mgr_get_from_string (account_mgr,
543 if (from_string && account_name) {
544 gchar *name = account_name;
545 ModestPair *pair = modest_pair_new ((gpointer) name,
546 (gpointer) from_string , TRUE);
547 transports = g_slist_prepend (transports, pair);
552 cursor = cursor->next;
554 g_slist_free (accounts); /* only free the accounts, not the elements,
555 * because they are used in the pairlist */
559 static void window_focus (GtkWindow *window,
563 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
567 scroll_drag_timeout (gpointer userdata)
569 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
570 ModestMsgEditWindowPrivate *priv;
572 /* It could happen that the window was already closed */
573 if (!GTK_WIDGET_VISIBLE (win))
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
578 correct_scroll_without_drag_check (win, TRUE);
580 priv->scroll_drag_timeout_id = 0;
586 correct_scroll_without_drag_check_idle (gpointer userdata)
588 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
589 ModestMsgEditWindowPrivate *priv;
591 GdkRectangle rectangle;
592 gint offset_min, offset_max;
596 /* It could happen that the window was already closed */
597 if (!GTK_WIDGET_VISIBLE (w))
600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
602 insert = gtk_text_buffer_get_insert (priv->text_buffer);
603 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
605 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
606 offset_min = priv->msg_body->allocation.y + rectangle.y;
607 offset_max = offset_min + rectangle.height;
609 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
610 offset_min = MAX (offset_min - 48, 0);
611 offset_max = MIN (offset_max + 48, vadj->upper);
613 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
615 priv->correct_scroll_idle = 0;
620 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
622 ModestMsgEditWindowPrivate *priv;
624 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
626 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
629 if (priv->correct_scroll_idle > 0) {
633 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
634 (GSourceFunc) correct_scroll_without_drag_check_idle,
640 correct_scroll (ModestMsgEditWindow *w)
642 ModestMsgEditWindowPrivate *priv;
644 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
645 if (gtk_grab_get_current () == priv->msg_body) {
646 if (priv->scroll_drag_timeout_id == 0) {
647 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
649 (GSourceFunc) scroll_drag_timeout,
656 correct_scroll_without_drag_check (w, TRUE);
660 text_buffer_end_user_action (GtkTextBuffer *buffer,
661 ModestMsgEditWindow *userdata)
664 correct_scroll (userdata);
668 text_buffer_mark_set (GtkTextBuffer *buffer,
671 ModestMsgEditWindow *userdata)
673 gtk_text_buffer_begin_user_action (buffer);
674 gtk_text_buffer_end_user_action (buffer);
678 cut_clipboard_check (GtkTextView *text_view,
681 GtkTextBuffer *buffer;
683 buffer = gtk_text_view_get_buffer (text_view);
684 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
685 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
690 copy_clipboard_check (GtkTextView *text_view,
693 GtkTextBuffer *buffer;
695 buffer = gtk_text_view_get_buffer (text_view);
696 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
697 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
702 attachment_deleted (ModestAttachmentsView *attachments_view,
705 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
710 connect_signals (ModestMsgEditWindow *obj)
712 ModestMsgEditWindowPrivate *priv;
714 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
716 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
717 G_CALLBACK (text_buffer_refresh_attributes), obj);
718 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
719 G_CALLBACK (text_buffer_can_undo), obj);
720 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
721 G_CALLBACK (text_buffer_can_redo), obj);
722 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
723 G_CALLBACK (body_changed), obj);
724 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
725 G_CALLBACK (body_insert_text), obj);
726 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
727 G_CALLBACK (body_changed), obj);
728 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
729 G_CALLBACK (text_buffer_end_user_action), obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
731 G_CALLBACK (text_buffer_mark_set), obj);
732 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
733 G_CALLBACK (text_buffer_apply_tag), obj);
734 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
735 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
736 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
737 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
738 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
739 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
741 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
742 G_CALLBACK (from_field_changed), obj);
744 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
745 G_CALLBACK (msg_body_focus), obj);
746 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
747 G_CALLBACK (msg_body_focus), obj);
748 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
749 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
750 "changed", G_CALLBACK (recpt_field_changed), obj);
751 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
752 "changed", G_CALLBACK (recpt_field_changed), obj);
753 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
754 "changed", G_CALLBACK (recpt_field_changed), obj);
755 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
756 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
757 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
759 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
760 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
762 priv->clipboard_change_handler_id =
763 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
764 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
765 priv->default_clipboard_change_handler_id =
766 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
767 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
769 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
770 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
771 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
775 init_wp_text_view_style ()
777 static gboolean initialized = FALSE;
780 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
786 init_window (ModestMsgEditWindow *obj)
788 GtkWidget *to_caption, *subject_caption;
789 GtkWidget *main_vbox;
790 ModestMsgEditWindowPrivate *priv;
791 GtkActionGroup *action_group;
792 ModestWindowPrivate *parent_priv;
793 GdkPixbuf *window_icon = NULL;
794 GError *error = NULL;
796 GtkSizeGroup *title_size_group;
797 GtkSizeGroup *value_size_group;
798 GtkWidget *window_box;
799 GtkWidget *window_align;
800 #if (GTK_MINOR_VERSION >= 10)
801 GdkAtom deserialize_type;
803 GtkWidget *from_send_hbox;
804 GtkWidget *send_icon;
806 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
807 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
809 parent_priv->ui_manager = gtk_ui_manager_new();
810 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
811 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
813 /* Add common actions */
814 gtk_action_group_add_actions (action_group,
815 modest_msg_edit_action_entries,
816 G_N_ELEMENTS (modest_msg_edit_action_entries),
818 gtk_action_group_add_actions (action_group,
819 hildon2_msg_edit_action_entries,
820 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
822 gtk_action_group_add_toggle_actions (action_group,
823 modest_msg_edit_toggle_action_entries,
824 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
826 gtk_action_group_add_radio_actions (action_group,
827 modest_msg_edit_alignment_radio_action_entries,
828 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
830 G_CALLBACK (modest_ui_actions_on_change_justify),
832 gtk_action_group_add_radio_actions (action_group,
833 modest_msg_edit_priority_action_entries,
834 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
836 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
838 gtk_action_group_add_radio_actions (action_group,
839 modest_msg_edit_file_format_action_entries,
840 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
841 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
842 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
844 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
845 g_object_unref (action_group);
847 /* Load the UI definition */
848 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
851 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
852 g_clear_error (&error);
855 /* Add accelerators */
856 gtk_window_add_accel_group (GTK_WINDOW (obj),
857 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
859 parent_priv->menubar = NULL;
861 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
862 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
864 /* Note: This ModestPairList* must exist for as long as the picker
865 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
866 * so it can't know how to manage its memory. */
867 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
868 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
870 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
871 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
872 _("mail_va_from"), priv->from_field);
873 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
874 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
875 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
877 priv->to_field = modest_recpt_editor_new ();
878 priv->cc_field = modest_recpt_editor_new ();
879 priv->bcc_field = modest_recpt_editor_new ();
880 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
881 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
882 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
883 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
884 priv->priority_icon = gtk_image_new ();
885 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
886 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
887 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
888 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
889 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
890 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
891 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
892 priv->attachments_view = modest_attachments_view_new (NULL);
893 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
894 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
896 priv->header_box = gtk_vbox_new (FALSE, 0);
898 to_caption = _create_addressbook_box
899 (title_size_group, value_size_group,
900 _("mail_va_to"), priv->to_field);
901 priv->cc_caption = _create_addressbook_box
902 (title_size_group, value_size_group,
903 _("mail_va_cc"), priv->cc_field);
904 priv->bcc_caption = _create_addressbook_box
905 (title_size_group, value_size_group,
906 _("mail_va_hotfix1"), priv->bcc_field);
907 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
908 _("mail_va_subject"), FALSE, priv->subject_box);
909 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
910 _("mail_va_attachment"),
912 priv->attachments_view,
913 HILDON_SIZE_AUTO_WIDTH |
914 HILDON_SIZE_AUTO_HEIGHT);
915 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
916 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
917 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
918 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 118, -1);
920 g_object_unref (title_size_group);
921 g_object_unref (value_size_group);
923 from_send_hbox = gtk_hbox_new (FALSE, 0);
924 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
925 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
927 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
928 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
929 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
930 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
931 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
932 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
933 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
935 init_wp_text_view_style ();
937 priv->msg_body = modest_wp_text_view_new ();
940 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
941 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
942 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
943 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
944 #if (GTK_MINOR_VERSION >= 10)
945 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
946 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
948 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
949 deserialize_type, TRUE);
951 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
953 priv->find_toolbar = hildon_find_toolbar_new (NULL);
954 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
956 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
958 priv->pannable = hildon_pannable_area_new ();
960 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
962 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
963 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
964 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
966 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
967 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
968 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
970 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
971 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
973 window_box = gtk_vbox_new (FALSE, 0);
974 gtk_container_add (GTK_CONTAINER(obj), window_box);
976 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
978 /* Set window icon */
979 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
981 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
982 g_object_unref (window_icon);
987 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
989 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
991 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
992 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
993 priv->clipboard_change_handler_id))
994 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
995 priv->clipboard_change_handler_id);
996 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
997 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
998 priv->default_clipboard_change_handler_id))
999 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1000 priv->default_clipboard_change_handler_id);
1002 if (priv->account_removed_handler_id &&
1003 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1004 priv->account_removed_handler_id))
1005 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1006 priv->account_removed_handler_id);
1010 modest_msg_edit_window_finalize (GObject *obj)
1012 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1014 /* Sanity check: shouldn't be needed, the window mgr should
1015 call this function before */
1016 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1018 if (priv->font_dialog != NULL) {
1019 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1022 if (priv->clipboard_text != NULL) {
1023 g_free (priv->clipboard_text);
1024 priv->clipboard_text = NULL;
1027 if (priv->draft_msg != NULL) {
1028 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1029 if (TNY_IS_HEADER (header)) {
1030 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1031 modest_window_mgr_unregister_header (mgr, header);
1033 g_object_unref (priv->draft_msg);
1034 priv->draft_msg = NULL;
1036 if (priv->outbox_msg != NULL) {
1037 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1038 if (TNY_IS_HEADER (header)) {
1039 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1040 modest_window_mgr_unregister_header (mgr, header);
1042 g_object_unref (priv->outbox_msg);
1043 priv->outbox_msg = NULL;
1045 if (priv->correct_scroll_idle > 0) {
1046 g_source_remove (priv->correct_scroll_idle);
1047 priv->correct_scroll_idle = 0;
1049 if (priv->scroll_drag_timeout_id > 0) {
1050 g_source_remove (priv->scroll_drag_timeout_id);
1051 priv->scroll_drag_timeout_id = 0;
1053 if (priv->clipboard_owner_idle > 0) {
1054 g_source_remove (priv->clipboard_owner_idle);
1055 priv->clipboard_owner_idle = 0;
1057 if (priv->original_account_name)
1058 g_free (priv->original_account_name);
1059 if (priv->original_mailbox)
1060 g_free (priv->original_mailbox);
1061 g_free (priv->msg_uid);
1062 g_free (priv->last_search);
1063 g_free (priv->references);
1064 g_free (priv->in_reply_to);
1065 g_object_unref (priv->faces_model);
1066 g_object_unref (priv->sizes_model);
1067 g_object_unref (priv->attachments);
1068 g_object_unref (priv->images);
1070 /* This had to stay alive for as long as the picker that used it: */
1071 modest_pair_list_free (priv->from_field_protos);
1073 G_OBJECT_CLASS(parent_class)->finalize (obj);
1077 pixbuf_size_prepared (GdkPixbufLoader *loader,
1080 ModestMsgEditWindow *self)
1082 gint new_height, new_width;
1085 new_height = height;
1089 if (width > IMAGE_MAX_WIDTH) {
1090 new_height = height * IMAGE_MAX_WIDTH / width;
1091 new_width = IMAGE_MAX_WIDTH;
1094 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1098 pixbuf_from_stream (TnyStream *stream,
1099 const gchar *mime_type,
1100 guint64 *stream_size,
1101 ModestMsgEditWindow *self)
1103 GdkPixbufLoader *loader;
1106 GError *error = NULL;
1110 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1112 if (loader == NULL) {
1117 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1119 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1121 tny_stream_reset (TNY_STREAM (stream));
1122 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1123 unsigned char read_buffer[128];
1125 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1127 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1130 /* Allow some UI responsiveness */
1131 while (gtk_events_pending ())
1132 gtk_main_iteration ();
1134 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1136 gdk_pixbuf_loader_close (loader, &error);
1139 g_error_free (error);
1140 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1142 g_object_ref (pixbuf);
1143 g_object_unref (loader);
1148 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1149 GdkPixbuf *new_pixbuf;
1151 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1152 gdk_pixbuf_get_width (pixbuf);
1153 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1154 g_object_unref (pixbuf);
1155 pixbuf = new_pixbuf;
1159 *stream_size = size;
1165 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1167 ModestMsgEditWindowPrivate *priv;
1170 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1172 g_object_ref (self);
1173 for (iter = tny_list_create_iterator (attachments);
1174 !tny_iterator_is_done (iter);
1175 tny_iterator_next (iter)) {
1176 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1177 const gchar *cid = tny_mime_part_get_content_id (part);
1178 const gchar *mime_type = tny_mime_part_get_content_type (part);
1179 if ((cid != NULL)&&(mime_type != NULL)) {
1180 guint64 stream_size;
1181 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1182 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1185 g_object_unref (stream);
1187 if (pixbuf != NULL) {
1188 priv->images_count ++;
1189 priv->images_size += stream_size;
1190 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1191 g_object_unref (pixbuf);
1194 g_object_unref (part);
1196 g_object_unref (iter);
1197 g_object_unref (self);
1201 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1203 TnyMimePart *parent = NULL;
1204 const gchar *content_type = NULL;
1205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1207 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1209 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1210 parent = g_object_ref (msg);
1211 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1212 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1215 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1216 iter = tny_list_create_iterator (parts);
1217 while (!tny_iterator_is_done (iter)) {
1219 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1220 content_type = tny_mime_part_get_content_type (part);
1221 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1225 g_object_unref (part);
1227 tny_iterator_next (iter);
1229 g_object_unref (iter);
1230 g_object_unref (parts);
1233 if (parent != NULL) {
1234 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1237 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1238 iter = tny_list_create_iterator (parts);
1239 while (!tny_iterator_is_done (iter)) {
1241 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1242 content_type = tny_mime_part_get_content_type (part);
1243 if (content_type && g_str_has_prefix (content_type, "image/")) {
1244 tny_list_prepend (priv->images, (GObject *) part);
1246 g_object_unref (part);
1247 tny_iterator_next (iter);
1249 g_object_unref (iter);
1250 g_object_unref (parts);
1251 g_object_unref (parent);
1256 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1259 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1261 for (iter = tny_list_create_iterator (attachments) ;
1262 !tny_iterator_is_done (iter);
1263 tny_iterator_next (iter)) {
1264 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1265 const gchar *cid = tny_mime_part_get_content_id (part);
1267 char *invalid = NULL;
1268 gint int_cid = strtol (cid, &invalid, 10);
1269 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1270 priv->next_cid = int_cid + 1;
1273 g_object_unref (part);
1275 g_object_unref (iter);
1279 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1282 gchar *to, *cc, *bcc, *subject;
1284 ModestMsgEditWindowPrivate *priv;
1285 ModestWindowPrivate *parent_priv;
1287 TnyHeaderFlags priority_flags;
1288 TnyFolder *msg_folder;
1289 gboolean is_html = FALSE;
1290 gboolean field_view_set;
1292 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1293 g_return_if_fail (TNY_IS_MSG (msg));
1295 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1296 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1298 header = tny_msg_get_header (msg);
1299 to = tny_header_dup_to (header);
1300 cc = tny_header_dup_cc (header);
1301 bcc = tny_header_dup_bcc (header);
1302 subject = tny_header_dup_subject (header);
1304 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1305 priority_flags = tny_header_get_priority (header);
1308 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1310 field_view_set = TRUE;
1312 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1313 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1314 gtk_widget_show (priv->cc_caption);
1315 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1316 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1317 gtk_widget_hide (priv->cc_caption);
1318 field_view_set = FALSE;
1320 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1322 field_view_set = TRUE;
1324 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1325 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1326 gtk_widget_show (priv->bcc_caption);
1327 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1328 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1329 gtk_widget_hide (priv->bcc_caption);
1330 field_view_set = FALSE;
1332 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1336 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1337 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1340 update_window_title (self);
1342 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1343 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1345 if ((body == NULL)||(body[0] == '\0')) {
1347 body = modest_text_utils_convert_to_html ("");
1350 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1351 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1354 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1357 /* Add attachments to the view */
1358 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1359 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1360 if (tny_list_get_length (priv->attachments) == 0) {
1361 gtk_widget_hide (priv->attachments_caption);
1363 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1364 gtk_widget_show_all (priv->attachments_caption);
1366 get_related_images (self, msg);
1367 update_next_cid (self, priv->attachments);
1368 update_next_cid (self, priv->images);
1369 replace_with_images (self, priv->images);
1371 if (preserve_is_rich && !is_html) {
1372 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1373 /* Get the default format required from configuration */
1374 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1375 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1378 /* Set the default focus depending on having already a To: field or not */
1379 if ((!to)||(*to == '\0')) {
1380 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1382 gtk_widget_grab_focus (priv->msg_body);
1385 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1387 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1388 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1390 modest_msg_edit_window_set_modified (self, FALSE);
1392 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1393 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1394 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1395 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1397 if (priv->msg_uid) {
1398 g_free (priv->msg_uid);
1399 priv->msg_uid = NULL;
1402 /* we should set a reference to the incoming message if it is a draft */
1403 msg_folder = tny_msg_get_folder (msg);
1405 if (modest_tny_folder_is_local_folder (msg_folder)) {
1406 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1407 if (type == TNY_FOLDER_TYPE_INVALID)
1408 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1410 if (type == TNY_FOLDER_TYPE_DRAFTS)
1411 priv->draft_msg = g_object_ref(msg);
1412 if (type == TNY_FOLDER_TYPE_OUTBOX)
1413 priv->outbox_msg = g_object_ref(msg);
1414 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1416 g_object_unref (msg_folder);
1427 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1429 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1430 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1431 GtkWidget *placeholder;
1432 GtkWidget *tool_item;
1437 GtkWidget *sizes_menu;
1438 GtkWidget *fonts_menu;
1444 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1445 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1446 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1447 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1449 /* Font color placeholder */
1450 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1451 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1454 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1455 priv->font_color_button = hildon_color_button_new ();
1456 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1457 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1458 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1459 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1460 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1461 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1462 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1463 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1465 G_CALLBACK (modest_msg_edit_window_color_button_change),
1468 /* Font size and face placeholder */
1469 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1470 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1472 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1473 priv->size_tool_button_label = gtk_label_new (NULL);
1474 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1475 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1476 size_text, "</span>", NULL);
1477 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1478 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1480 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1481 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1482 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1483 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1484 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1485 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1486 gtk_widget_set_sensitive (arrow, FALSE);
1487 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1488 sizes_menu = gtk_menu_new ();
1489 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1490 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1493 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1494 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1496 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1500 if (wp_font_size[size_index] == 12)
1501 priv->current_size_index = size_index;
1505 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1506 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1507 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1508 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1509 priv->font_size_toolitem = tool_item;
1512 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1513 priv->font_tool_button_label = gtk_label_new (NULL);
1514 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1515 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1516 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1518 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1519 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1520 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1521 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1522 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1523 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1524 gtk_widget_set_sensitive (arrow, FALSE);
1525 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1526 fonts_menu = gtk_menu_new ();
1527 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1528 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1531 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1533 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1534 0, wp_get_font_name (font_index),
1537 if (font_index == DEFAULT_FONT)
1538 priv->current_face_index = font_index;
1540 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1541 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1542 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1543 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1544 priv->font_face_toolitem = tool_item;
1546 /* Set expand and homogeneous for remaining items */
1547 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1548 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1549 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1550 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1551 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1552 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1553 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1554 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1555 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1557 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1558 will not show the tool items added to the placeholders) */
1559 gtk_widget_show_all (parent_priv->toolbar);
1561 /* Set the no show all *after* showing all items. We do not
1562 want the toolbar to be shown with a show all because it
1563 could go agains the gconf setting regarding showing or not
1564 the toolbar of the editor window */
1565 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1571 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1574 ModestWindowPrivate *parent_priv;
1575 ModestMsgEditWindowPrivate *priv;
1576 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1577 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1578 ModestWindowMgr *mgr = NULL;
1580 g_return_val_if_fail (msg, NULL);
1581 g_return_val_if_fail (account_name, NULL);
1583 mgr = modest_runtime_get_window_mgr ();
1585 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1588 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1590 /* Menubar. Update the state of some toggles */
1591 priv->from_field_protos = get_transports ();
1592 priv->original_mailbox = NULL;
1593 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1594 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1595 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1596 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1597 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1598 priv->original_mailbox = g_strdup (mailbox);
1599 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1600 /* We set the first mailbox as the active mailbox */
1601 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1602 if (priv->original_mailbox != NULL)
1603 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1604 (gpointer) priv->original_mailbox);
1606 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1607 (gpointer) account_name);
1609 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1611 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1612 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1614 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1615 hildon_touch_selector_get_current_text
1616 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1617 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1618 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1621 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1623 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1625 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1626 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1628 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1630 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1631 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1632 /* Add common dimming rules */
1633 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1634 modest_msg_edit_window_toolbar_dimming_entries,
1635 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1636 MODEST_WINDOW (obj));
1637 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1638 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1639 MODEST_WINDOW (obj));
1640 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1641 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1642 MODEST_WINDOW (obj));
1643 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1644 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1645 MODEST_WINDOW (obj));
1646 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1647 G_CALLBACK (modest_ui_dimming_rules_on_send),
1648 MODEST_WINDOW (obj));
1649 /* Insert dimming rules group for this window */
1650 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1651 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1653 /* Setup app menu */
1654 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1656 /* Checks the dimming rules */
1657 g_object_unref (toolbar_rules_group);
1658 g_object_unref (clipboard_rules_group);
1659 gtk_widget_hide (priv->priority_icon);
1660 gtk_widget_queue_resize (priv->subject_box);
1661 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1663 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1665 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1666 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1667 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1668 priv->update_caption_visibility = TRUE;
1670 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1672 /* Track account-removed signal, this window should be closed
1673 in the case we're creating a mail associated to the account
1675 priv->account_removed_handler_id =
1676 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1678 G_CALLBACK(on_account_removed),
1681 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1683 return (ModestWindow*) obj;
1687 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1689 GString **string_buffer = (GString **) user_data;
1691 *string_buffer = g_string_append (*string_buffer, buffer);
1697 * @result: A new string which should be freed with g_free().
1700 get_formatted_data (ModestMsgEditWindow *edit_window)
1702 ModestMsgEditWindowPrivate *priv;
1703 GString *string_buffer = g_string_new ("");
1705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1707 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1709 modest_text_utils_hyperlinkify (string_buffer);
1711 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1713 return g_string_free (string_buffer, FALSE);
1718 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1721 const gchar *account_name;
1722 ModestMsgEditWindowPrivate *priv;
1723 TnyIterator *att_iter;
1724 const gchar *picker_active_id;
1726 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1730 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1731 g_return_val_if_fail (picker_active_id, NULL);
1732 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1734 /* don't free these (except from) */
1735 data = g_slice_new0 (MsgData);
1736 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1737 data->account_name = g_strdup (account_name);
1738 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1739 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1740 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1741 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1742 data->references = g_strdup (priv->references);
1743 data->in_reply_to = g_strdup (priv->in_reply_to);
1744 if (priv->draft_msg) {
1745 data->draft_msg = g_object_ref (priv->draft_msg);
1746 } else if (priv->outbox_msg) {
1747 data->draft_msg = g_object_ref (priv->outbox_msg);
1749 data->draft_msg = NULL;
1752 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1754 gtk_text_buffer_get_bounds (buf, &b, &e);
1755 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1757 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1758 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1760 data->html_body = NULL;
1762 /* deep-copy the data */
1763 att_iter = tny_list_create_iterator (priv->attachments);
1764 data->attachments = NULL;
1765 while (!tny_iterator_is_done (att_iter)) {
1766 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1767 if (!(TNY_IS_MIME_PART(part))) {
1768 g_warning ("strange data in attachment list");
1769 g_object_unref (part);
1770 tny_iterator_next (att_iter);
1773 data->attachments = g_list_append (data->attachments,
1775 tny_iterator_next (att_iter);
1777 g_object_unref (att_iter);
1779 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1780 att_iter = tny_list_create_iterator (priv->images);
1781 data->images = NULL;
1782 while (!tny_iterator_is_done (att_iter)) {
1783 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1785 if (!(TNY_IS_MIME_PART(part))) {
1786 g_warning ("strange data in attachment list");
1787 g_object_unref (part);
1788 tny_iterator_next (att_iter);
1791 cid = tny_mime_part_get_content_id (part);
1793 gchar *image_tag_id;
1794 GtkTextTag *image_tag;
1796 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1797 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1798 g_free (image_tag_id);
1800 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1802 ((gtk_text_iter_has_tag (&iter, image_tag))||
1803 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1804 data->images = g_list_append (data->images,
1805 g_object_ref (part));
1807 g_object_unref (part);
1808 tny_iterator_next (att_iter);
1810 g_object_unref (att_iter);
1812 data->priority_flags = priv->priority_flags;
1819 unref_gobject (GObject *obj, gpointer data)
1821 if (!G_IS_OBJECT(obj))
1823 g_object_unref (obj);
1827 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1830 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1838 g_free (data->from);
1839 g_free (data->subject);
1840 g_free (data->plain_body);
1841 g_free (data->html_body);
1842 g_free (data->account_name);
1843 g_free (data->references);
1844 g_free (data->in_reply_to);
1846 if (data->draft_msg != NULL) {
1847 g_object_unref (data->draft_msg);
1848 data->draft_msg = NULL;
1851 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1852 g_list_free (data->attachments);
1853 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1854 g_list_free (data->images);
1856 g_slice_free (MsgData, data);
1860 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1862 guint64 *parts_size)
1864 ModestMsgEditWindowPrivate *priv;
1866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1868 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1870 /* TODO: add images */
1871 *parts_size += priv->images_size;
1872 *parts_count += priv->images_count;
1877 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1880 ModestMsgEditWindowPrivate *priv = NULL;
1881 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1883 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1885 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1887 return MODEST_MSG_EDIT_FORMAT_HTML;
1889 return MODEST_MSG_EDIT_FORMAT_TEXT;
1893 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1894 ModestMsgEditFormat format)
1896 ModestMsgEditWindowPrivate *priv;
1897 ModestWindowPrivate *parent_priv;
1899 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1900 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1901 parent_priv = MODEST_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);
1906 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1908 case MODEST_MSG_EDIT_FORMAT_TEXT:
1909 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1910 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1913 g_return_if_reached ();
1917 ModestMsgEditFormatState *
1918 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1920 ModestMsgEditFormatState *format_state = NULL;
1921 ModestMsgEditWindowPrivate *priv;
1922 WPTextBufferFormat *buffer_format;
1924 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1926 buffer_format = g_new0 (WPTextBufferFormat, 1);
1927 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1929 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1931 format_state = g_new0 (ModestMsgEditFormatState, 1);
1932 format_state->bold = buffer_format->bold&0x1;
1933 format_state->italics = buffer_format->italic&0x1;
1934 format_state->bullet = buffer_format->bullet&0x1;
1935 format_state->color = buffer_format->color;
1936 format_state->font_size = buffer_format->font_size;
1937 format_state->font_family = wp_get_font_name (buffer_format->font);
1938 format_state->justification = buffer_format->justification;
1939 g_free (buffer_format);
1941 return format_state;
1946 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1947 const ModestMsgEditFormatState *format_state)
1949 ModestMsgEditWindowPrivate *priv;
1950 WPTextBufferFormat *buffer_format;
1951 WPTextBufferFormat *current_format;
1953 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1954 g_return_if_fail (format_state != NULL);
1956 buffer_format = g_new0 (WPTextBufferFormat, 1);
1957 current_format = g_new0 (WPTextBufferFormat, 1);
1959 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1960 gtk_widget_grab_focus (priv->msg_body);
1961 buffer_format->bold = (format_state->bold != FALSE);
1962 buffer_format->italic = (format_state->italics != FALSE);
1963 buffer_format->color = format_state->color;
1964 buffer_format->font_size = format_state->font_size;
1965 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1966 buffer_format->justification = format_state->justification;
1967 buffer_format->bullet = format_state->bullet;
1969 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1971 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1972 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1973 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1974 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1975 buffer_format->cs.font = (buffer_format->font != current_format->font);
1976 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1977 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1979 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1980 if (buffer_format->cs.bold) {
1981 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1982 GINT_TO_POINTER (buffer_format->bold&0x1));
1984 if (buffer_format->cs.italic) {
1985 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1986 GINT_TO_POINTER (buffer_format->italic&0x1));
1988 if (buffer_format->cs.color) {
1989 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1990 GINT_TO_POINTER (&(buffer_format->color)));
1992 if (buffer_format->cs.font_size) {
1993 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1994 GINT_TO_POINTER (buffer_format->font_size));
1996 if (buffer_format->cs.justification) {
1997 switch (buffer_format->justification) {
1998 case GTK_JUSTIFY_LEFT:
1999 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2000 GINT_TO_POINTER(TRUE));
2002 case GTK_JUSTIFY_CENTER:
2003 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2004 GINT_TO_POINTER(TRUE));
2006 case GTK_JUSTIFY_RIGHT:
2007 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2008 GINT_TO_POINTER(TRUE));
2015 if (buffer_format->cs.font) {
2016 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2017 GINT_TO_POINTER (buffer_format->font));
2019 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2020 if (buffer_format->cs.bullet) {
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2022 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2024 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2026 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2028 g_free (buffer_format);
2029 g_free (current_format);
2031 /* Check dimming rules */
2032 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2033 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2037 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2039 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2041 ModestWindowPrivate *parent_priv;
2042 ModestMsgEditWindowPrivate *priv;
2044 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2045 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2047 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2048 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2049 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2050 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2052 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2053 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2054 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2057 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2059 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2060 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2062 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2063 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2065 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2066 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2069 switch (buffer_format->justification)
2071 case GTK_JUSTIFY_LEFT:
2072 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2074 case GTK_JUSTIFY_CENTER:
2075 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2077 case GTK_JUSTIFY_RIGHT:
2078 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2085 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2087 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2088 G_CALLBACK (modest_msg_edit_window_color_button_change),
2090 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2091 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2092 G_CALLBACK (modest_msg_edit_window_color_button_change),
2095 if (priv->current_size_index != buffer_format->font_size) {
2099 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2100 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2104 priv->current_size_index = buffer_format->font_size;
2106 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2107 markup = g_strconcat ("<span font_family='Sans'>",
2108 size_text, "</span>", NULL);
2110 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2114 gtk_tree_path_free (path);
2117 if (priv->current_face_index != buffer_format->font) {
2121 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2122 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2126 priv->current_face_index = buffer_format->font;
2127 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2128 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2129 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2136 g_free (buffer_format);
2140 #ifdef MODEST_HILDON_VERSION_0
2142 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2145 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2146 ModestMsgEditWindowPrivate *priv;
2147 GtkWidget *dialog = NULL;
2149 GdkColor *new_color = NULL;
2151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2152 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2154 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2155 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2156 g_free (buffer_format);
2158 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2159 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2160 if (new_color != NULL) {
2161 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2162 (gpointer) new_color);
2165 gtk_widget_destroy (dialog);
2170 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2173 ModestMsgEditWindowPrivate *priv;
2174 GtkWidget *dialog = NULL;
2176 GdkColor *old_color = NULL;
2177 const GdkColor *new_color = NULL;
2179 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2180 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2182 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2183 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2185 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2186 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2187 if (new_color != NULL)
2188 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2190 gtk_widget_destroy (dialog);
2196 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2199 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2200 ModestMsgEditWindowPrivate *priv;
2201 GtkWidget *dialog = NULL;
2203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2204 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2206 dialog = hildon_color_chooser_new ();
2207 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2208 g_free (buffer_format);
2210 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2212 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2213 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2216 gtk_widget_destroy (dialog);
2221 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2224 ModestMsgEditWindowPrivate *priv;
2225 GtkWidget *dialog = NULL;
2226 GdkColor *old_color = NULL;
2228 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2229 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2231 dialog = hildon_color_chooser_new ();
2232 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2234 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2236 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2237 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2239 gtk_widget_destroy (dialog);
2242 #endif /*!MODEST_HILDON_VERSION_0*/
2247 create_stream_for_uri (const gchar* uri)
2252 TnyStream *result = NULL;
2254 GnomeVFSHandle *handle = NULL;
2255 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2256 if (test == GNOME_VFS_OK) {
2257 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2258 /* Streams over OBEX (Bluetooth) are not seekable but
2259 * we expect them to be (we might need to read them
2260 * several times). So if this is a Bluetooth URI just
2261 * read the whole file into memory (this is not a fast
2262 * protocol so we can assume that these files are not
2263 * going to be very big) */
2264 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2265 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2266 TnyStream *memstream = tny_camel_mem_stream_new ();
2267 tny_stream_write_to_stream (vfssstream, memstream);
2268 g_object_unref (vfssstream);
2271 result = vfssstream;
2279 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2282 ModestMsgEditWindowPrivate *priv;
2283 GtkWidget *dialog = NULL;
2285 GSList *uris = NULL;
2286 GSList *uri_node = NULL;
2288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2290 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2291 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2292 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2294 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2296 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2297 GTK_WINDOW (dialog), GTK_WINDOW (window));
2299 response = gtk_dialog_run (GTK_DIALOG (dialog));
2301 case GTK_RESPONSE_OK:
2303 gchar *current_folder;
2304 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2305 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2306 if (current_folder && current_folder != '\0') {
2308 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2309 current_folder, &err);
2311 g_debug ("Error storing latest used folder: %s", err->message);
2315 g_free (current_folder);
2321 gtk_widget_destroy (dialog);
2323 g_object_ref (window);
2324 /* The operation could take some time so allow the dialog to be closed */
2325 while (gtk_events_pending ())
2326 gtk_main_iteration ();
2328 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2330 GnomeVFSHandle *handle = NULL;
2331 GnomeVFSResult result;
2332 GtkTextIter position;
2333 GtkTextMark *insert_mark;
2335 uri = (const gchar *) uri_node->data;
2336 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2337 if (result == GNOME_VFS_OK) {
2339 GnomeVFSFileInfo *info;
2340 gchar *filename, *basename, *escaped_filename;
2341 TnyMimePart *mime_part;
2343 const gchar *mime_type = NULL;
2344 GnomeVFSURI *vfs_uri;
2345 guint64 stream_size;
2347 gnome_vfs_close (handle);
2348 vfs_uri = gnome_vfs_uri_new (uri);
2350 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2351 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2352 g_free (escaped_filename);
2353 gnome_vfs_uri_unref (vfs_uri);
2354 info = gnome_vfs_file_info_new ();
2356 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2357 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2359 mime_type = gnome_vfs_file_info_get_mime_type (info);
2361 mime_part = tny_platform_factory_new_mime_part
2362 (modest_runtime_get_platform_factory ());
2364 TnyStream *stream = create_stream_for_uri (uri);
2366 if (stream == NULL) {
2368 modest_platform_information_banner (NULL, NULL,
2369 _FM("sfil_ib_opening_not_allowed"));
2371 g_object_unref (mime_part);
2372 gnome_vfs_file_info_unref (info);
2376 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2378 content_id = g_strdup_printf ("%d", priv->next_cid);
2379 tny_mime_part_set_content_id (mime_part, content_id);
2380 g_free (content_id);
2383 basename = g_path_get_basename (filename);
2384 tny_mime_part_set_filename (mime_part, basename);
2387 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2389 if (pixbuf != NULL) {
2390 priv->images_size += stream_size;
2391 priv->images_count ++;
2392 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2393 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2394 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2395 tny_mime_part_get_content_id (mime_part), pixbuf);
2396 g_object_unref (pixbuf);
2398 tny_list_prepend (priv->images, (GObject *) mime_part);
2399 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2401 modest_platform_information_banner (NULL, NULL,
2402 _("mail_ib_file_operation_failed"));
2406 g_object_unref (mime_part);
2407 gnome_vfs_file_info_unref (info);
2411 g_object_unref (window);
2415 on_attach_file_response (GtkDialog *dialog,
2419 GSList *uris = NULL;
2421 GnomeVFSFileSize total_size, allowed_size;
2422 ModestMsgEditWindow *window;
2423 ModestMsgEditWindowPrivate *priv;
2428 case GTK_RESPONSE_OK:
2430 gchar *current_folder;
2432 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2433 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2434 if (current_folder && current_folder != '\0') {
2436 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2437 current_folder, &err);
2439 g_debug ("Error storing latest used folder: %s", err->message);
2443 g_free (current_folder);
2450 window = MODEST_MSG_EDIT_WINDOW (user_data);
2451 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2453 /* allowed size is the maximum size - what's already there */
2454 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2455 &att_num, &att_size);
2456 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2459 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2461 const gchar *uri = (const gchar *) uri_node->data;
2464 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2466 if (total_size > allowed_size) {
2467 g_warning ("%s: total size: %u",
2468 __FUNCTION__, (unsigned int)total_size);
2471 allowed_size -= total_size;
2473 g_slist_foreach (uris, (GFunc) g_free, NULL);
2474 g_slist_free (uris);
2476 gtk_widget_destroy (GTK_WIDGET (dialog));
2480 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2482 GtkWidget *dialog = NULL;
2483 ModestMsgEditWindowPrivate *priv;
2486 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2490 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2493 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2494 GTK_FILE_CHOOSER_ACTION_OPEN);
2495 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2496 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2497 if (conf_folder && conf_folder[0] != '\0') {
2498 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2501 /* Set the default folder to images folder */
2502 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2503 ".documents", NULL);
2504 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2505 g_free (docs_folder);
2507 g_free (conf_folder);
2508 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2509 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2510 GTK_WINDOW (dialog), GTK_WINDOW (window));
2512 /* Connect to response & show */
2513 g_signal_connect (dialog, "response",
2514 G_CALLBACK (on_attach_file_response), window);
2515 gtk_widget_show (dialog);
2520 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2522 GnomeVFSFileSize allowed_size)
2525 GnomeVFSHandle *handle = NULL;
2526 ModestMsgEditWindowPrivate *priv;
2527 GnomeVFSResult result;
2528 GnomeVFSFileSize size = 0;
2529 g_return_val_if_fail (window, 0);
2530 g_return_val_if_fail (uri, 0);
2532 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2534 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2535 if (result == GNOME_VFS_OK) {
2536 TnyMimePart *mime_part;
2538 const gchar *mime_type = NULL;
2540 gchar *escaped_filename;
2543 GnomeVFSFileInfo *info;
2544 GnomeVFSURI *vfs_uri;
2546 gnome_vfs_close (handle);
2547 vfs_uri = gnome_vfs_uri_new (uri);
2550 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2551 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2552 g_free (escaped_filename);
2553 gnome_vfs_uri_unref (vfs_uri);
2555 info = gnome_vfs_file_info_new ();
2557 if (gnome_vfs_get_file_info (uri,
2559 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2561 mime_type = gnome_vfs_file_info_get_mime_type (info);
2562 mime_part = tny_platform_factory_new_mime_part
2563 (modest_runtime_get_platform_factory ());
2565 /* try to get the attachment's size; this may fail for weird
2566 * file systems, like obex, upnp... */
2567 if (allowed_size != 0 &&
2568 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2570 if (size > allowed_size) {
2571 modest_platform_information_banner (NULL, NULL,
2572 _FM("sfil_ib_opening_not_allowed"));
2577 g_warning ("%s: could not get attachment size", __FUNCTION__);
2579 stream = create_stream_for_uri (uri);
2581 if (stream == NULL) {
2583 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2585 g_object_unref (mime_part);
2587 gnome_vfs_file_info_unref (info);
2591 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2592 g_object_unref (stream);
2594 content_id = g_strdup_printf ("%d", priv->next_cid);
2595 tny_mime_part_set_content_id (mime_part, content_id);
2596 g_free (content_id);
2599 basename = g_path_get_basename (filename);
2600 tny_mime_part_set_filename (mime_part, basename);
2603 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2604 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2606 info->size == 0, info->size);
2607 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2608 gtk_widget_show_all (priv->attachments_caption);
2609 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2611 g_object_unref (mime_part);
2612 gnome_vfs_file_info_unref (info);
2619 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2622 ModestMsgEditWindowPrivate *priv;
2625 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2626 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2628 if (att_list == NULL) {
2629 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2630 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2631 g_object_unref (att_list);
2636 g_object_ref (att_list);
2639 if (tny_list_get_length (att_list) == 0) {
2640 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2642 gboolean dialog_response;
2643 gchar *message = NULL;
2644 gchar *filename = NULL;
2646 if (tny_list_get_length (att_list) == 1) {
2648 iter = tny_list_create_iterator (att_list);
2649 part = (TnyMimePart *) tny_iterator_get_current (iter);
2650 g_object_unref (iter);
2651 if (TNY_IS_MSG (part)) {
2652 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2654 filename = tny_header_dup_subject (header);
2655 g_object_unref (header);
2657 if (filename == NULL) {
2658 filename = g_strdup (_("mail_va_no_subject"));
2661 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2663 g_object_unref (part);
2665 filename = g_strdup ("");
2667 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2668 "emev_nc_delete_attachments",
2669 tny_list_get_length (att_list)), filename);
2672 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2676 if (dialog_response != GTK_RESPONSE_OK) {
2677 g_object_unref (att_list);
2681 for (iter = tny_list_create_iterator (att_list);
2682 !tny_iterator_is_done (iter);
2683 tny_iterator_next (iter)) {
2684 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2685 const gchar *att_id;
2686 tny_list_remove (priv->attachments, (GObject *) mime_part);
2688 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2690 if (tny_list_get_length (priv->attachments) == 0)
2691 gtk_widget_hide (priv->attachments_caption);
2692 att_id = tny_mime_part_get_content_id (mime_part);
2694 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2696 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2697 g_object_unref (mime_part);
2699 g_object_unref (iter);
2702 g_object_unref (att_list);
2704 /* if the last attachment has been removed, focus the Subject: field */
2705 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2706 gtk_widget_grab_focus (priv->subject_field);
2710 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2713 ModestMsgEditWindowPrivate *priv;
2714 GdkColor *new_color;
2715 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2717 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2718 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2721 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2723 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2725 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2727 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2732 font_size_clicked (GtkToolButton *button,
2733 ModestMsgEditWindow *window)
2735 ModestMsgEditWindowPrivate *priv;
2736 GtkWidget *selector, *dialog;
2738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2740 selector = hildon_touch_selector_new ();
2741 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2742 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2744 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2745 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2746 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2748 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2752 WPTextBufferFormat format;
2754 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2756 memset (&format, 0, sizeof (format));
2757 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2759 format.cs.font_size = TRUE;
2760 format.cs.text_position = TRUE;
2761 format.cs.font = TRUE;
2762 format.font_size = new_index;
2763 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2765 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2766 GINT_TO_POINTER (new_index)))
2767 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2769 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2770 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2771 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2772 size_text, "</span>", NULL);
2774 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2778 gtk_widget_destroy (dialog);
2780 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2785 font_face_clicked (GtkToolButton *button,
2786 ModestMsgEditWindow *window)
2788 ModestMsgEditWindowPrivate *priv;
2789 GtkWidget *selector, *dialog;
2790 GtkCellRenderer *renderer;
2792 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2794 selector = hildon_touch_selector_new ();
2795 renderer = gtk_cell_renderer_text_new ();
2796 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2797 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2798 renderer, "family", 0, "text", 0, NULL);
2799 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2801 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2802 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2803 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2805 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2806 gint new_font_index;
2810 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2811 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2812 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2816 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2818 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2819 GINT_TO_POINTER(new_font_index)))
2820 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2822 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2823 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2825 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2829 gtk_tree_path_free (path);
2832 gtk_widget_destroy (dialog);
2834 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2839 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2842 ModestMsgEditWindowPrivate *priv = NULL;
2843 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2845 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2846 if (!priv->update_caption_visibility)
2849 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2851 gtk_widget_show (priv->cc_caption);
2853 gtk_widget_hide (priv->cc_caption);
2855 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2859 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2862 ModestMsgEditWindowPrivate *priv = NULL;
2863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2866 if (!priv->update_caption_visibility)
2869 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2871 gtk_widget_show (priv->bcc_caption);
2873 gtk_widget_hide (priv->bcc_caption);
2875 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2879 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2880 ModestRecptEditor *editor)
2882 ModestMsgEditWindowPrivate *priv;
2884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2885 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2887 /* we check for low-mem; in that case, show a warning, and don't allow
2888 * for the addressbook
2890 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2895 if (editor == NULL) {
2896 GtkWidget *view_focus;
2897 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2899 /* This code should be kept in sync with ModestRecptEditor. The
2900 textview inside the recpt editor is the one that really gets the
2901 focus. As it's inside a scrolled window, and this one inside the
2902 hbox recpt editor inherits from, we'll need to go up in the
2903 hierarchy to know if the text view is part of the recpt editor
2904 or if it's a different text entry */
2906 if (gtk_widget_get_parent (view_focus)) {
2907 GtkWidget *first_parent;
2909 first_parent = gtk_widget_get_parent (view_focus);
2910 if (gtk_widget_get_parent (first_parent) &&
2911 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2912 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2917 editor = MODEST_RECPT_EDITOR (priv->to_field);
2921 modest_address_book_select_addresses (editor);
2926 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2928 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2930 modest_msg_edit_window_open_addressbook (window, NULL);
2934 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2935 gboolean show_toolbar)
2937 ModestWindowPrivate *parent_priv;
2938 ModestMsgEditWindowPrivate *priv;
2940 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2942 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2944 /* We can not just use the code of
2945 modest_msg_edit_window_setup_toolbar because it has a
2946 mixture of both initialization and creation code. */
2948 gint current_format;
2949 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2950 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2951 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2952 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2954 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2957 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2962 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2963 TnyHeaderFlags priority_flags)
2965 ModestMsgEditWindowPrivate *priv;
2966 ModestWindowPrivate *parent_priv;
2968 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2970 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2971 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2973 if (priv->priority_flags != priority_flags) {
2974 GtkAction *priority_action = NULL;
2976 priv->priority_flags = priority_flags;
2978 switch (priority_flags) {
2979 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2980 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2981 MODEST_HEADER_ICON_HIGH,
2982 HILDON_ICON_SIZE_SMALL);
2983 gtk_widget_show (priv->priority_icon);
2984 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2985 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2987 case TNY_HEADER_FLAG_LOW_PRIORITY:
2988 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2989 MODEST_HEADER_ICON_LOW,
2990 HILDON_ICON_SIZE_SMALL);
2991 gtk_widget_show (priv->priority_icon);
2992 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2993 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2996 gtk_widget_hide (priv->priority_icon);
2997 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2998 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3001 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3002 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3004 gtk_widget_queue_resize (priv->subject_box);
3008 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3011 ModestMsgEditWindowPrivate *priv;
3012 ModestWindowPrivate *parent_priv;
3013 gint current_format;
3015 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3017 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3020 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3021 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3023 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3025 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3026 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3029 if (current_format != file_format) {
3030 switch (file_format) {
3031 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3032 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3033 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3035 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3039 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3040 response = gtk_dialog_run (GTK_DIALOG (dialog));
3041 gtk_widget_destroy (dialog);
3042 if (response == GTK_RESPONSE_OK) {
3043 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3044 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3046 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3047 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3052 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3053 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3054 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3059 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3062 ModestMsgEditWindowPrivate *priv;
3063 WPTextBufferFormat oldfmt, fmt;
3064 gint old_position = 0;
3068 GdkColor *color = NULL;
3069 gboolean bold, bold_set, italic, italic_set;
3070 gboolean underline, underline_set;
3071 gboolean strikethrough, strikethrough_set;
3072 gboolean position_set;
3073 gboolean font_size_set, font_set, color_set;
3076 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3077 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3079 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3080 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3081 GTK_WINDOW(dialog), GTK_WINDOW (window));
3083 /* First we get the currently selected font information */
3084 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3086 switch (oldfmt.text_position) {
3087 case TEXT_POSITION_NORMAL:
3090 case TEXT_POSITION_SUPERSCRIPT:
3098 g_object_set (G_OBJECT (dialog),
3099 "bold", oldfmt.bold != FALSE,
3100 "bold-set", !oldfmt.cs.bold,
3101 "underline", oldfmt.underline != FALSE,
3102 "underline-set", !oldfmt.cs.underline,
3103 "italic", oldfmt.italic != FALSE,
3104 "italic-set", !oldfmt.cs.italic,
3105 "strikethrough", oldfmt.strikethrough != FALSE,
3106 "strikethrough-set", !oldfmt.cs.strikethrough,
3107 "color", &oldfmt.color,
3108 "color-set", !oldfmt.cs.color,
3109 "size", wp_font_size[oldfmt.font_size],
3110 "size-set", !oldfmt.cs.font_size,
3111 "position", old_position,
3112 "position-set", !oldfmt.cs.text_position,
3113 "family", wp_get_font_name (oldfmt.font),
3114 "family-set", !oldfmt.cs.font,
3117 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3118 GTK_WINDOW (dialog), GTK_WINDOW (window));
3119 gtk_widget_show_all (dialog);
3120 priv->font_dialog = dialog;
3121 response = gtk_dialog_run (GTK_DIALOG (dialog));
3122 priv->font_dialog = NULL;
3123 if (response == GTK_RESPONSE_OK) {
3125 g_object_get( dialog,
3127 "bold-set", &bold_set,
3128 "underline", &underline,
3129 "underline-set", &underline_set,
3131 "italic-set", &italic_set,
3132 "strikethrough", &strikethrough,
3133 "strikethrough-set", &strikethrough_set,
3135 "color-set", &color_set,
3137 "size-set", &font_size_set,
3138 "family", &font_name,
3139 "family-set", &font_set,
3140 "position", &position,
3141 "position-set", &position_set,
3146 if (response == GTK_RESPONSE_OK) {
3147 memset(&fmt, 0, sizeof(fmt));
3153 fmt.italic = italic;
3154 fmt.cs.italic = TRUE;
3156 if (underline_set) {
3157 fmt.underline = underline;
3158 fmt.cs.underline = TRUE;
3160 if (strikethrough_set) {
3161 fmt.strikethrough = strikethrough;
3162 fmt.cs.strikethrough = TRUE;
3167 ? TEXT_POSITION_NORMAL
3168 : ( ( position == 1 )
3169 ? TEXT_POSITION_SUPERSCRIPT
3170 : TEXT_POSITION_SUBSCRIPT );
3171 fmt.cs.text_position = TRUE;
3172 fmt.font_size = oldfmt.font_size;
3176 fmt.cs.color = TRUE;
3179 fmt.font = wp_get_font_index(font_name,
3184 if (font_size_set) {
3185 fmt.cs.font_size = TRUE;
3186 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3188 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3189 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3191 gtk_widget_destroy (dialog);
3193 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3197 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3199 ModestMsgEditWindowPrivate *priv;
3201 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3202 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3204 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3206 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3207 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3211 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3213 ModestMsgEditWindowPrivate *priv;
3215 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3216 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3218 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3220 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3221 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3226 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3228 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3230 priv->can_undo = can_undo;
3234 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 priv->can_redo = can_redo;
3242 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3244 ModestMsgEditWindowPrivate *priv;
3245 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3246 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3248 return priv->can_undo;
3252 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3254 ModestMsgEditWindowPrivate *priv;
3255 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 return priv->can_redo;
3263 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3266 GtkTextIter match_start, match_end;
3268 if (image_id == NULL)
3271 gtk_text_buffer_get_start_iter (buffer, &iter);
3273 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3274 GSList *tags = gtk_text_iter_get_tags (&match_start);
3276 for (node = tags; node != NULL; node = g_slist_next (node)) {
3277 GtkTextTag *tag = (GtkTextTag *) node->data;
3278 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3279 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3280 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3282 offset = gtk_text_iter_get_offset (&match_start);
3283 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3284 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3288 gtk_text_iter_forward_char (&iter);
3293 message_is_empty (ModestMsgEditWindow *window)
3295 ModestMsgEditWindowPrivate *priv = NULL;
3297 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3300 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3301 * so we can ignore markup.
3303 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3306 count = gtk_text_buffer_get_char_count (buf);
3312 msg_body_focus (GtkWidget *focus,
3313 GdkEventFocus *event,
3317 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3318 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3319 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3324 recpt_field_changed (GtkTextBuffer *buffer,
3325 ModestMsgEditWindow *editor)
3327 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3328 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3332 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3334 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3335 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3339 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3342 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3343 GtkTextBuffer *buffer;
3345 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3346 gtk_text_buffer_set_modified (buffer, modified);
3347 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3348 gtk_text_buffer_set_modified (buffer, modified);
3349 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3350 gtk_text_buffer_set_modified (buffer, modified);
3351 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3355 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3357 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3358 const char *account_name;
3359 GtkTextBuffer *buffer;
3361 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3362 if (gtk_text_buffer_get_modified (buffer))
3364 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3365 if (gtk_text_buffer_get_modified (buffer))
3367 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3368 if (gtk_text_buffer_get_modified (buffer))
3370 if (gtk_text_buffer_get_modified (priv->text_buffer))
3373 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3374 if (priv->original_mailbox) {
3375 if (!account_name || strcmp (account_name, priv->original_mailbox))
3377 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3388 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3390 ModestMsgEditWindowPrivate *priv = NULL;
3392 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3393 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3395 /* check if there's no recipient added */
3396 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3397 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3398 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3399 /* no recipient contents, then select contacts */
3400 modest_msg_edit_window_open_addressbook (window, NULL);
3404 g_object_ref (window);
3405 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3406 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3407 g_object_unref (window);
3410 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3411 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3412 g_object_unref (window);
3415 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3416 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3417 g_object_unref (window);
3421 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3422 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3423 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3424 g_object_unref (window);
3431 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3432 ModestMsgEditWindow *window)
3434 modest_msg_edit_window_offer_attach_file (window);
3438 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3440 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3442 return priv->clipboard_text;
3446 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3448 ModestMsgEditWindow *window)
3450 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3451 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3454 /* It could happen that the window was already closed */
3455 if (!GTK_WIDGET_VISIBLE (window))
3458 g_object_ref (window);
3459 text = gtk_clipboard_wait_for_text (selection_clipboard);
3461 if (priv->clipboard_text != NULL) {
3462 g_free (priv->clipboard_text);
3464 priv->clipboard_text = text;
3466 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3468 g_object_unref (window);
3471 static gboolean clipboard_owner_change_idle (gpointer userdata)
3473 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3474 ModestMsgEditWindowPrivate *priv;
3476 gdk_threads_enter ();
3477 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3478 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3480 priv->clipboard_owner_idle = 0;
3481 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3482 gdk_threads_leave ();
3488 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3490 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3491 if (priv->clipboard_owner_idle == 0) {
3492 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3493 clipboard_owner_change_idle,
3494 g_object_ref (window),
3500 subject_field_move_cursor (GtkEntry *entry,
3501 GtkMovementStep step,
3506 /* It could happen that the window was already closed */
3507 if (!GTK_WIDGET_VISIBLE (window))
3510 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3514 update_window_title (ModestMsgEditWindow *window)
3516 ModestMsgEditWindowPrivate *priv = NULL;
3517 const gchar *subject;
3519 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3520 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3521 if (subject == NULL || subject[0] == '\0')
3522 subject = _("mail_va_new_email");
3524 gtk_window_set_title (GTK_WINDOW (window), subject);
3530 body_insert_text (GtkTextBuffer *buffer,
3531 GtkTextIter *location,
3534 ModestMsgEditWindow *window)
3536 GtkTextIter end_iter;
3539 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3541 offset = gtk_text_iter_get_offset (&end_iter);
3543 if (offset + len > MAX_BODY_LENGTH) {
3544 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3545 if (offset < MAX_BODY_LENGTH)
3549 /* Prevent endless recursion */
3550 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3551 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3552 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3553 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3555 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3559 if (offset + len > MAX_BODY_LENGTH) {
3560 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3561 _CS("ckdg_ib_maximum_characters_reached"));
3566 subject_field_changed (GtkEditable *editable,
3567 ModestMsgEditWindow *window)
3569 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3570 update_window_title (window);
3571 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3572 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3573 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3576 subject_field_insert_text (GtkEditable *editable,
3578 gint new_text_length,
3580 ModestMsgEditWindow *window)
3582 GString *result = g_string_new ("");
3584 gint result_len = 0;
3585 const gchar *entry_text = NULL;
3588 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3589 old_length = g_utf8_strlen (entry_text, -1);
3591 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3592 gunichar c = g_utf8_get_char_validated (current, 8);
3593 /* Invalid unichar, stop */
3599 result = g_string_append_unichar (result, c);
3603 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3604 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3607 /* Prevent endless recursion */
3608 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3609 g_signal_emit_by_name (editable, "insert-text",
3610 (gpointer) result->str, (gpointer) result->len,
3611 (gpointer) position, (gpointer) window);
3612 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3616 if (result_len + old_length > 1000) {
3617 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3618 _CS("ckdg_ib_maximum_characters_reached"));
3620 g_string_free (result, TRUE);
3624 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3627 ModestMsgEditWindowPrivate *priv = NULL;
3629 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3630 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3632 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3635 gtk_widget_show_all (priv->find_toolbar);
3636 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3638 gtk_widget_hide_all (priv->find_toolbar);
3639 gtk_widget_grab_focus (priv->msg_body);
3644 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3646 GtkTextIter *match_start,
3647 GtkTextIter *match_end)
3649 GtkTextIter end_iter;
3650 gchar *str_casefold;
3653 gchar *range_casefold;
3656 gboolean result = FALSE;
3663 gtk_text_iter_forward_to_end (&end_iter);
3665 str_casefold = g_utf8_casefold (str, -1);
3666 str_chars_n = strlen (str);
3668 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3669 range_casefold = g_utf8_casefold (range_text, -1);
3670 range_chars_n = strlen (range_casefold);
3672 if (range_chars_n < str_chars_n) {
3673 g_free (str_casefold);
3674 g_free (range_text);
3675 g_free (range_casefold);
3679 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3680 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3681 if (!g_utf8_collate (range_subtext, str_casefold)) {
3682 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3684 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3685 match_start, match_end, NULL)) {
3686 g_warning ("Matched string with collate, but not matched in model");
3688 g_free (found_text);
3690 g_free (range_subtext);
3694 g_free (str_casefold);
3695 g_free (range_text);
3696 g_free (range_casefold);
3703 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3704 ModestMsgEditWindow *window)
3706 gchar *current_search = NULL;
3707 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3709 GtkTextIter selection_start, selection_end;
3710 GtkTextIter match_start, match_end;
3711 gboolean continue_search = FALSE;
3713 if (message_is_empty (window)) {
3714 g_free (priv->last_search);
3715 priv->last_search = NULL;
3716 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3720 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3721 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3722 g_free (current_search);
3723 g_free (priv->last_search);
3724 priv->last_search = NULL;
3725 /* Information banner about empty search */
3726 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3730 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3731 continue_search = TRUE;
3733 g_free (priv->last_search);
3734 priv->last_search = g_strdup (current_search);
3737 if (continue_search) {
3738 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3739 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3740 &match_start, &match_end);
3742 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3744 GtkTextIter buffer_start;
3745 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3746 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3747 &match_start, &match_end);
3749 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3752 /* Mark as selected the string found in search */
3754 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3755 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3756 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3758 g_free (priv->last_search);
3759 priv->last_search = NULL;
3761 g_free (current_search);
3765 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3767 ModestMsgEditWindowPrivate *priv;
3769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3774 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3777 ModestMsgEditWindowPrivate *priv;
3779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3784 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3785 ModestMsgEditWindow *window)
3787 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3791 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3794 ModestMsgEditWindowPrivate *priv;
3795 TnyHeader *header = NULL;
3797 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3798 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3802 if (priv->draft_msg != NULL) {
3803 g_object_unref (priv->draft_msg);
3806 if (draft != NULL) {
3807 g_object_ref (draft);
3808 header = tny_msg_get_header (draft);
3809 if (priv->msg_uid) {
3810 g_free (priv->msg_uid);
3811 priv->msg_uid = NULL;
3813 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3816 priv->draft_msg = draft;
3820 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3821 GtkTextIter *start, GtkTextIter *end,
3824 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3825 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3828 if (tag == NULL) return;
3829 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3830 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3831 replace_with_images (window, priv->images);
3836 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3839 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3841 g_return_if_fail (TNY_IS_MIME_PART (part));
3842 tny_list_prepend (priv->attachments, (GObject *) part);
3843 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3844 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3845 gtk_widget_show_all (priv->attachments_caption);
3846 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3850 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3852 ModestMsgEditWindowPrivate *priv;
3854 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3857 return priv->msg_uid;
3861 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3862 ModestMsgEditWindowWidgetType widget_type)
3864 ModestMsgEditWindowPrivate *priv;
3866 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3867 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3869 switch (widget_type) {
3870 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3871 return priv->msg_body;
3873 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3874 return priv->to_field;
3876 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3877 return priv->cc_field;
3879 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3880 return priv->bcc_field;
3882 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3883 return priv->subject_field;
3885 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3886 return priv->attachments_view;
3894 remove_tags (WPTextBuffer *buffer)
3896 GtkTextIter start, end;
3898 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3899 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3901 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3905 on_account_removed (TnyAccountStore *account_store,
3906 TnyAccount *account,
3909 /* Do nothing if it's a store account, because we use the
3910 transport to send the messages */
3911 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3912 const gchar *parent_acc = NULL;
3913 const gchar *our_acc = NULL;
3915 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3916 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3917 /* Close this window if I'm showing a message of the removed account */
3918 if (strcmp (parent_acc, our_acc) == 0)
3919 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3923 static void update_signature (ModestMsgEditWindow *self,
3924 const gchar *old_account,
3925 const gchar *new_account)
3927 ModestMsgEditWindowPrivate *priv;
3928 gboolean has_old_signature, has_new_signature;
3930 GtkTextIter match_start, match_end;
3931 ModestAccountMgr *mgr;
3933 gchar *full_signature;
3935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3937 gtk_text_buffer_begin_user_action (priv->text_buffer);
3939 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3940 mgr = modest_runtime_get_account_mgr ();
3944 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3945 if (has_old_signature) {
3946 full_signature = g_strconcat ("\n--\n", signature, NULL);
3947 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3948 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3950 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3951 &match_start, &match_end, NULL)) {
3954 g_free (full_signature);
3959 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3960 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3961 if (has_new_signature) {
3962 full_signature = g_strconcat ("\n--\n", signature, NULL);
3963 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3964 g_free (full_signature);
3967 gtk_text_buffer_end_user_action (priv->text_buffer);
3971 from_field_changed (HildonPickerButton *button,
3972 ModestMsgEditWindow *self)
3974 ModestMsgEditWindowPrivate *priv;
3975 gchar *old_account, *new_account;
3977 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3979 old_account = priv->last_from_account;
3980 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3981 new_account = priv->last_from_account;
3983 update_signature (self, old_account, new_account);
3987 typedef struct _MessageSettingsHelper {
3988 ModestMsgEditWindow *window;
3989 GSList *priority_group;
3990 GSList *format_group;
3991 GtkToggleButton *current_priority;
3992 GtkToggleButton *current_format;
3993 } MessageSettingsHelper;
3996 on_priority_toggle (GtkToggleButton *button,
3997 MessageSettingsHelper *helper)
4000 ModestMsgEditWindowPrivate *priv;
4002 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4003 if (gtk_toggle_button_get_active (button)) {
4005 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4006 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4007 if ((node_button != button) &&
4008 gtk_toggle_button_get_active (node_button)) {
4009 gtk_toggle_button_set_active (node_button, FALSE);
4012 helper->current_priority = button;
4014 gboolean found = FALSE;
4015 /* If no one is active, activate it again */
4016 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4017 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4018 if (gtk_toggle_button_get_active (node_button)) {
4024 gtk_toggle_button_set_active (button, TRUE);
4030 on_format_toggle (GtkToggleButton *button,
4031 MessageSettingsHelper *helper)
4034 ModestMsgEditWindowPrivate *priv;
4036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4037 if (gtk_toggle_button_get_active (button)) {
4039 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4040 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4041 if ((node_button != button) &&
4042 gtk_toggle_button_get_active (node_button)) {
4043 gtk_toggle_button_set_active (node_button, FALSE);
4046 helper->current_format = button;
4048 gboolean found = FALSE;
4049 /* If no one is active, activate it again */
4050 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4051 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4052 if (gtk_toggle_button_get_active (node_button)) {
4058 gtk_toggle_button_set_active (button, TRUE);
4065 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4070 GtkWidget *priority_hbox;
4071 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4072 GtkWidget *captioned;
4073 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4074 GtkWidget *format_hbox;
4075 GtkWidget *html_toggle, *text_toggle;
4076 ModestMsgEditWindowPrivate *priv;
4077 MessageSettingsHelper helper = {0,};
4079 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4080 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4081 helper.window = window;
4082 helper.priority_group = NULL;
4083 helper.format_group = NULL;
4085 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4086 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4088 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4089 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4090 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4091 vbox = gtk_vbox_new (FALSE, 0);
4092 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4093 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4094 gtk_container_add (GTK_CONTAINER (align), vbox);
4095 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4096 gtk_widget_show (align);
4097 gtk_widget_show (vbox);
4099 /* Priority toggles */
4100 priority_hbox = gtk_hbox_new (TRUE, 0);
4101 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4102 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4103 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4104 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4105 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4106 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4107 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4108 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4109 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4110 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4111 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4112 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4113 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4114 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4115 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4116 gtk_widget_show_all (priority_hbox);
4117 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4118 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4119 gtk_widget_show (captioned);
4120 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4122 /* format toggles */
4123 format_hbox = gtk_hbox_new (TRUE, 0);
4124 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4125 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4126 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4127 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4128 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4129 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4130 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4131 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4132 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4133 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4134 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4135 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4136 gtk_widget_show_all (format_hbox);
4137 gtk_widget_show (format_hbox);
4138 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4141 g_object_unref (title_sizegroup);
4142 g_object_unref (value_sizegroup);
4144 /* Set current values */
4145 switch (priv->priority_flags) {
4146 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4147 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4148 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4150 case TNY_HEADER_FLAG_LOW_PRIORITY:
4151 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4152 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4155 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4156 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4160 switch (modest_msg_edit_window_get_format (window)) {
4161 case MODEST_MSG_EDIT_FORMAT_TEXT:
4162 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4163 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4165 case MODEST_MSG_EDIT_FORMAT_HTML:
4167 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4168 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4172 /* Signal connects */
4173 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4174 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4175 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4176 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4177 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4179 /* Save settings if the user clicked on done */
4180 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4181 TnyHeaderFlags flags;
4182 ModestMsgEditFormat old_format, new_format;
4184 /* Set priority flags */
4185 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4186 if (priv->priority_flags != flags)
4187 modest_msg_edit_window_set_priority_flags (window, flags);
4189 /* Set edit format */
4190 old_format = modest_msg_edit_window_get_format (window);
4191 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4192 if (old_format != new_format) {
4193 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4194 modest_msg_edit_window_set_file_format (window, file_format);
4198 gtk_widget_destroy (dialog);
4199 g_slist_free (helper.priority_group);
4203 on_message_settings (GtkAction *action,
4204 ModestMsgEditWindow *window)
4206 modest_msg_edit_window_show_msg_settings_dialog (window);
4210 on_cc_button_toggled (HildonCheckButton *button,
4211 ModestMsgEditWindow *window)
4213 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4215 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4216 hildon_check_button_get_active (button));
4220 on_bcc_button_toggled (HildonCheckButton *button,
4221 ModestMsgEditWindow *window)
4223 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4225 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4226 hildon_check_button_get_active (button));
4230 setup_menu (ModestMsgEditWindow *self)
4232 ModestMsgEditWindowPrivate *priv = NULL;
4234 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4236 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4238 /* Settings menu buttons */
4239 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4240 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4242 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4243 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4244 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4246 priv->cc_button = hildon_check_button_new (0);
4247 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4248 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4250 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4252 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4253 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4254 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4255 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4257 priv->bcc_button = hildon_check_button_new (0);
4258 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4259 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4261 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4263 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4264 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4265 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4266 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4268 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4269 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4270 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4271 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: add attachment"), NULL,
4272 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4274 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4275 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4276 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4277 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4278 APP_MENU_CALLBACK (on_message_settings),
4280 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4281 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4286 emit_open_addressbook (GtkButton *button,
4287 ModestRecptEditor *editor)
4289 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4293 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4294 const gchar *label, GtkWidget *control)
4296 GtkWidget *abook_button;
4299 GtkWidget *label_widget;
4301 box = gtk_hbox_new (FALSE, 0);
4303 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4304 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4306 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4307 label_widget = gtk_label_new (label);
4308 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4309 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4311 gtk_container_add (GTK_CONTAINER (align), abook_button);
4312 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4313 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4314 if (title_size_group)
4315 gtk_size_group_add_widget (title_size_group, label_widget);
4316 if (value_size_group)
4317 gtk_size_group_add_widget (value_size_group, control);
4319 g_signal_connect (G_OBJECT (abook_button), "clicked",
4320 G_CALLBACK (emit_open_addressbook), control);