1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 48
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
191 const gchar *label, GtkWidget *control);
192 static void DEBUG_BUFFER (WPTextBuffer *buffer)
196 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
198 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
199 while (!gtk_text_iter_is_end (&iter)) {
200 GString *output = g_string_new ("");
201 GSList *toggled_tags;
204 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
205 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
206 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
207 GtkTextTag *tag = (GtkTextTag *) node->data;
209 g_object_get (G_OBJECT (tag), "name", &name, NULL);
210 output = g_string_append (output, name);
211 g_string_append (output, " ");
213 output = g_string_append (output, "] OPENED [ ");
214 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
215 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
216 GtkTextTag *tag = (GtkTextTag *) node->data;
218 g_object_get (G_OBJECT (tag), "name", &name, NULL);
219 output = g_string_append (output, name);
220 g_string_append (output, " ");
222 output = g_string_append (output, "]\n");
223 g_message ("%s", output->str);
224 g_string_free (output, TRUE);
225 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
227 g_message ("END BUFFER");
231 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
232 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
236 /* static gboolean */
237 /* on_key_pressed (GtkWidget *self, */
238 /* GdkEventKey *event, */
239 /* gpointer user_data); */
241 /* list my signals */
248 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
249 struct _ModestMsgEditWindowPrivate {
251 GtkWidget *header_box;
253 ModestPairList *from_field_protos;
254 GtkWidget *from_field;
255 gchar *last_from_account;
256 gchar *original_account_name;
261 gchar *original_mailbox;
265 GtkWidget *bcc_field;
266 GtkWidget *subject_field;
267 GtkWidget *attachments_view;
268 GtkWidget *priority_icon;
269 GtkWidget *subject_box;
271 GtkWidget *cc_caption;
272 GtkWidget *bcc_caption;
273 gboolean update_caption_visibility;
274 GtkWidget *attachments_caption;
276 GtkTextBuffer *text_buffer;
278 GtkWidget *font_size_toolitem;
279 GtkWidget *font_face_toolitem;
280 GtkWidget *font_color_button;
281 GtkWidget *font_color_toolitem;
282 GSList *font_items_group;
283 GtkTreeModel *faces_model;
284 gint current_face_index;
285 GtkWidget *font_tool_button_label;
286 GtkTreeModel *sizes_model;
287 gint current_size_index;
288 GtkWidget *size_tool_button_label;
290 GtkWidget *find_toolbar;
293 GtkWidget *font_dialog;
296 guint correct_scroll_idle;
297 guint scroll_drag_timeout_id;
301 TnyList *attachments;
306 TnyHeaderFlags priority_flags;
308 gboolean can_undo, can_redo;
309 gulong clipboard_change_handler_id;
310 gulong default_clipboard_change_handler_id;
311 gulong account_removed_handler_id;
312 guint clipboard_owner_idle;
313 gchar *clipboard_text;
322 GtkWidget *cc_button;
323 GtkWidget *bcc_button;
326 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
327 MODEST_TYPE_MSG_EDIT_WINDOW, \
328 ModestMsgEditWindowPrivate))
330 static GtkWindowClass *parent_class = NULL;
332 /* uncomment the following if you have defined any signals */
333 /* static guint signals[LAST_SIGNAL] = {0}; */
336 modest_msg_edit_window_get_type (void)
338 static GType my_type = 0;
340 static const GTypeInfo my_info = {
341 sizeof(ModestMsgEditWindowClass),
342 NULL, /* base init */
343 NULL, /* base finalize */
344 (GClassInitFunc) modest_msg_edit_window_class_init,
345 NULL, /* class finalize */
346 NULL, /* class data */
347 sizeof(ModestMsgEditWindow),
349 (GInstanceInitFunc) modest_msg_edit_window_init,
352 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
353 "ModestMsgEditWindow",
361 save_state (ModestWindow *self)
363 modest_widget_memory_save (modest_runtime_get_conf(),
364 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
369 restore_settings (ModestMsgEditWindow *self)
371 ModestConf *conf = NULL;
373 conf = modest_runtime_get_conf ();
375 /* Dim at start clipboard actions */
376 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
381 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
383 GObjectClass *gobject_class;
384 ModestWindowClass *modest_window_class;
385 gobject_class = (GObjectClass*) klass;
386 modest_window_class = (ModestWindowClass*) klass;
388 parent_class = g_type_class_peek_parent (klass);
389 gobject_class->finalize = modest_msg_edit_window_finalize;
391 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
392 modest_window_class->save_state_func = save_state;
393 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
395 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
399 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
401 ModestMsgEditWindowPrivate *priv;
402 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
404 priv->msg_body = NULL;
405 priv->from_field = NULL;
406 priv->to_field = NULL;
407 priv->cc_field = NULL;
408 priv->bcc_field = NULL;
409 priv->subject_field = NULL;
410 priv->attachments = TNY_LIST (tny_simple_list_new ());
411 priv->images = TNY_LIST (tny_simple_list_new ());
412 priv->images_size = 0;
413 priv->images_count = 0;
416 priv->cc_caption = NULL;
417 priv->bcc_caption = NULL;
418 priv->update_caption_visibility = FALSE;
420 priv->priority_flags = 0;
422 priv->find_toolbar = NULL;
423 priv->last_search = NULL;
425 priv->draft_msg = NULL;
426 priv->outbox_msg = NULL;
427 priv->msg_uid = NULL;
429 priv->can_undo = FALSE;
430 priv->can_redo = FALSE;
431 priv->clipboard_change_handler_id = 0;
432 priv->default_clipboard_change_handler_id = 0;
433 priv->account_removed_handler_id = 0;
434 priv->clipboard_owner_idle = 0;
435 priv->clipboard_text = NULL;
438 priv->scroll_drag_timeout_id = 0;
439 priv->correct_scroll_idle = 0;
440 priv->last_upper = 0.0;
442 priv->font_dialog = NULL;
443 priv->app_menu = NULL;
445 priv->references = NULL;
446 priv->in_reply_to = NULL;
448 if (!is_wp_text_buffer_started) {
449 is_wp_text_buffer_started = TRUE;
450 wp_text_buffer_library_init ();
455 hildon_program_add_window (hildon_program_get_instance(),
460 multimailbox_get_default_mailbox (const gchar *account_name)
462 gchar *transport_account;
463 gchar *result = NULL;
465 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
467 TNY_ACCOUNT_TYPE_TRANSPORT);
468 if (transport_account) {
470 ModestProtocolRegistry *registry;
472 registry = modest_runtime_get_protocol_registry ();
474 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
475 MODEST_ACCOUNT_PROTO, TRUE);
477 ModestProtocol *protocol =
478 modest_protocol_registry_get_protocol_by_name (registry,
479 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
481 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
482 ModestPairList *pair_list;
484 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
487 ModestPair *pair = (ModestPair *) pair_list->data;
488 result = g_strdup ((const gchar *) pair->first);
489 modest_pair_list_free (pair_list);
500 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
502 static ModestPairList*
503 get_transports (void)
505 GSList *transports = NULL;
507 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
508 GSList *accounts = modest_account_mgr_account_names (account_mgr,
509 TRUE /* only enabled accounts. */);
511 GSList *cursor = accounts;
513 gchar *account_name = cursor->data;
516 gchar *transport_account;
517 gboolean multi_mailbox = FALSE;
518 ModestProtocol *protocol = NULL;
520 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
522 transport_account = modest_account_mgr_get_server_account_name
523 (modest_runtime_get_account_mgr (),
525 TNY_ACCOUNT_TYPE_TRANSPORT);
526 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
527 ModestPairList *pair_list;
528 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
531 transports = g_slist_concat (transports, pair_list);
532 multi_mailbox = TRUE;
537 if (!multi_mailbox) {
538 gchar *from_string = NULL;
540 from_string = modest_account_mgr_get_from_string (account_mgr,
542 if (from_string && account_name) {
543 gchar *name = account_name;
544 ModestPair *pair = modest_pair_new ((gpointer) name,
545 (gpointer) from_string , TRUE);
546 transports = g_slist_prepend (transports, pair);
551 cursor = cursor->next;
553 g_slist_free (accounts); /* only free the accounts, not the elements,
554 * because they are used in the pairlist */
558 static void window_focus (GtkWindow *window,
562 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
566 scroll_drag_timeout (gpointer userdata)
568 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
569 ModestMsgEditWindowPrivate *priv;
571 /* It could happen that the window was already closed */
572 if (!GTK_WIDGET_VISIBLE (win))
575 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
577 correct_scroll_without_drag_check (win, TRUE);
579 priv->scroll_drag_timeout_id = 0;
585 correct_scroll_without_drag_check_idle (gpointer userdata)
587 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
588 ModestMsgEditWindowPrivate *priv;
590 GdkRectangle rectangle;
591 gint offset_min, offset_max;
595 /* It could happen that the window was already closed */
596 if (!GTK_WIDGET_VISIBLE (w))
599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
601 insert = gtk_text_buffer_get_insert (priv->text_buffer);
602 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
604 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
605 offset_min = priv->msg_body->allocation.y + rectangle.y;
606 offset_max = offset_min + rectangle.height;
608 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
609 offset_min = MAX (offset_min - 48, 0);
610 offset_max = MIN (offset_max + 48, vadj->upper);
612 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
614 priv->correct_scroll_idle = 0;
619 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
621 ModestMsgEditWindowPrivate *priv;
623 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
625 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
628 if (priv->correct_scroll_idle > 0) {
632 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
633 (GSourceFunc) correct_scroll_without_drag_check_idle,
639 correct_scroll (ModestMsgEditWindow *w)
641 ModestMsgEditWindowPrivate *priv;
643 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
644 if (gtk_grab_get_current () == priv->msg_body) {
645 if (priv->scroll_drag_timeout_id == 0) {
646 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
648 (GSourceFunc) scroll_drag_timeout,
655 correct_scroll_without_drag_check (w, TRUE);
659 text_buffer_end_user_action (GtkTextBuffer *buffer,
660 ModestMsgEditWindow *userdata)
663 correct_scroll (userdata);
667 text_buffer_mark_set (GtkTextBuffer *buffer,
670 ModestMsgEditWindow *userdata)
672 gtk_text_buffer_begin_user_action (buffer);
673 gtk_text_buffer_end_user_action (buffer);
677 cut_clipboard_check (GtkTextView *text_view,
680 GtkTextBuffer *buffer;
682 buffer = gtk_text_view_get_buffer (text_view);
683 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
684 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
689 copy_clipboard_check (GtkTextView *text_view,
692 GtkTextBuffer *buffer;
694 buffer = gtk_text_view_get_buffer (text_view);
695 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
696 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
701 attachment_deleted (ModestAttachmentsView *attachments_view,
704 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
709 connect_signals (ModestMsgEditWindow *obj)
711 ModestMsgEditWindowPrivate *priv;
713 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
715 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
716 G_CALLBACK (text_buffer_refresh_attributes), obj);
717 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
718 G_CALLBACK (text_buffer_can_undo), obj);
719 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
720 G_CALLBACK (text_buffer_can_redo), obj);
721 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
722 G_CALLBACK (body_changed), obj);
723 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
724 G_CALLBACK (body_insert_text), obj);
725 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
726 G_CALLBACK (body_changed), obj);
727 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
728 G_CALLBACK (text_buffer_end_user_action), obj);
729 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
730 G_CALLBACK (text_buffer_mark_set), obj);
731 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
732 G_CALLBACK (text_buffer_apply_tag), obj);
733 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
734 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
735 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
736 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
737 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
738 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
740 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
741 G_CALLBACK (from_field_changed), obj);
743 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
744 G_CALLBACK (msg_body_focus), obj);
745 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
746 G_CALLBACK (msg_body_focus), obj);
747 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
748 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
749 "changed", G_CALLBACK (recpt_field_changed), obj);
750 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
751 "changed", G_CALLBACK (recpt_field_changed), obj);
752 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
753 "changed", G_CALLBACK (recpt_field_changed), obj);
754 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
755 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
756 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
758 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
759 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
761 priv->clipboard_change_handler_id =
762 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
763 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
764 priv->default_clipboard_change_handler_id =
765 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
766 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
768 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
769 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
770 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
774 init_wp_text_view_style ()
776 static gboolean initialized = FALSE;
779 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
785 init_window (ModestMsgEditWindow *obj)
787 GtkWidget *to_caption, *subject_caption;
788 GtkWidget *main_vbox;
789 ModestMsgEditWindowPrivate *priv;
790 GtkActionGroup *action_group;
791 ModestWindowPrivate *parent_priv;
792 GdkPixbuf *window_icon = NULL;
793 GError *error = NULL;
795 GtkSizeGroup *title_size_group;
796 GtkSizeGroup *value_size_group;
797 GtkWidget *window_box;
798 GtkWidget *window_align;
799 #if (GTK_MINOR_VERSION >= 10)
800 GdkAtom deserialize_type;
803 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
804 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
806 parent_priv->ui_manager = gtk_ui_manager_new();
807 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
808 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
810 /* Add common actions */
811 gtk_action_group_add_actions (action_group,
812 modest_msg_edit_action_entries,
813 G_N_ELEMENTS (modest_msg_edit_action_entries),
815 gtk_action_group_add_actions (action_group,
816 hildon2_msg_edit_action_entries,
817 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
819 gtk_action_group_add_toggle_actions (action_group,
820 modest_msg_edit_toggle_action_entries,
821 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
823 gtk_action_group_add_radio_actions (action_group,
824 modest_msg_edit_alignment_radio_action_entries,
825 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
827 G_CALLBACK (modest_ui_actions_on_change_justify),
829 gtk_action_group_add_radio_actions (action_group,
830 modest_msg_edit_priority_action_entries,
831 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
833 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
835 gtk_action_group_add_radio_actions (action_group,
836 modest_msg_edit_file_format_action_entries,
837 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
838 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
839 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
841 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
842 g_object_unref (action_group);
844 /* Load the UI definition */
845 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
848 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
849 g_clear_error (&error);
852 /* Add accelerators */
853 gtk_window_add_accel_group (GTK_WINDOW (obj),
854 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
856 parent_priv->menubar = NULL;
858 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
859 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
861 /* Note: This ModestPairList* must exist for as long as the picker
862 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
863 * so it can't know how to manage its memory. */
864 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
865 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
867 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
868 modest_maemo_utils_set_hbutton_layout (title_size_group, value_size_group,
869 _("mail_va_from"), priv->from_field);
870 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
871 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
872 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
874 priv->to_field = modest_recpt_editor_new ();
875 priv->cc_field = modest_recpt_editor_new ();
876 priv->bcc_field = modest_recpt_editor_new ();
877 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
878 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
879 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
880 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
881 priv->priority_icon = gtk_image_new ();
882 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
883 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
884 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
885 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
886 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
887 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
888 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
889 priv->attachments_view = modest_attachments_view_new (NULL);
890 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
891 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
893 priv->header_box = gtk_vbox_new (FALSE, 0);
895 to_caption = _create_addressbook_box
896 (title_size_group, value_size_group,
897 _("mail_va_to"), priv->to_field);
898 priv->cc_caption = _create_addressbook_box
899 (title_size_group, value_size_group,
900 _("mail_va_cc"), priv->cc_field);
901 priv->bcc_caption = _create_addressbook_box
902 (title_size_group, value_size_group,
903 _("mail_va_hotfix1"), priv->bcc_field);
904 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
905 _("mail_va_subject"), FALSE, priv->subject_box);
906 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (title_size_group, value_size_group,
907 _("mail_va_attachment"),
909 priv->attachments_view,
910 HILDON_SIZE_AUTO_WIDTH |
911 HILDON_SIZE_AUTO_HEIGHT);
912 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), value_size_group); */
913 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), value_size_group); */
914 /* modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), value_size_group); */
915 g_object_unref (title_size_group);
916 g_object_unref (value_size_group);
918 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->from_field, FALSE, FALSE, 0);
919 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
920 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
921 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
922 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
923 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
924 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
926 init_wp_text_view_style ();
928 priv->msg_body = modest_wp_text_view_new ();
931 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
932 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
933 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
934 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
935 #if (GTK_MINOR_VERSION >= 10)
936 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
937 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
939 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
940 deserialize_type, TRUE);
942 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
944 priv->find_toolbar = hildon_find_toolbar_new (NULL);
945 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
947 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
949 priv->pannable = hildon_pannable_area_new ();
951 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
953 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
954 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
955 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
957 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
958 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
959 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
961 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
962 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
964 window_box = gtk_vbox_new (FALSE, 0);
965 gtk_container_add (GTK_CONTAINER(obj), window_box);
967 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
969 /* Set window icon */
970 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
972 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
973 g_object_unref (window_icon);
978 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
980 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
982 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
983 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
984 priv->clipboard_change_handler_id))
985 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
986 priv->clipboard_change_handler_id);
987 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
988 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
989 priv->default_clipboard_change_handler_id))
990 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
991 priv->default_clipboard_change_handler_id);
993 if (priv->account_removed_handler_id &&
994 g_signal_handler_is_connected (modest_runtime_get_account_store (),
995 priv->account_removed_handler_id))
996 g_signal_handler_disconnect(modest_runtime_get_account_store (),
997 priv->account_removed_handler_id);
1001 modest_msg_edit_window_finalize (GObject *obj)
1003 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1005 /* Sanity check: shouldn't be needed, the window mgr should
1006 call this function before */
1007 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1009 if (priv->font_dialog != NULL) {
1010 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1013 if (priv->clipboard_text != NULL) {
1014 g_free (priv->clipboard_text);
1015 priv->clipboard_text = NULL;
1018 if (priv->draft_msg != NULL) {
1019 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1020 if (TNY_IS_HEADER (header)) {
1021 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1022 modest_window_mgr_unregister_header (mgr, header);
1024 g_object_unref (priv->draft_msg);
1025 priv->draft_msg = NULL;
1027 if (priv->outbox_msg != NULL) {
1028 TnyHeader *header = tny_msg_get_header (priv->outbox_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->outbox_msg);
1034 priv->outbox_msg = NULL;
1036 if (priv->correct_scroll_idle > 0) {
1037 g_source_remove (priv->correct_scroll_idle);
1038 priv->correct_scroll_idle = 0;
1040 if (priv->scroll_drag_timeout_id > 0) {
1041 g_source_remove (priv->scroll_drag_timeout_id);
1042 priv->scroll_drag_timeout_id = 0;
1044 if (priv->clipboard_owner_idle > 0) {
1045 g_source_remove (priv->clipboard_owner_idle);
1046 priv->clipboard_owner_idle = 0;
1048 if (priv->original_account_name)
1049 g_free (priv->original_account_name);
1050 if (priv->original_mailbox)
1051 g_free (priv->original_mailbox);
1052 g_free (priv->msg_uid);
1053 g_free (priv->last_search);
1054 g_free (priv->references);
1055 g_free (priv->in_reply_to);
1056 g_object_unref (priv->faces_model);
1057 g_object_unref (priv->sizes_model);
1058 g_object_unref (priv->attachments);
1059 g_object_unref (priv->images);
1061 /* This had to stay alive for as long as the picker that used it: */
1062 modest_pair_list_free (priv->from_field_protos);
1064 G_OBJECT_CLASS(parent_class)->finalize (obj);
1068 pixbuf_size_prepared (GdkPixbufLoader *loader,
1071 ModestMsgEditWindow *self)
1073 gint new_height, new_width;
1076 new_height = height;
1080 if (width > IMAGE_MAX_WIDTH) {
1081 new_height = height * IMAGE_MAX_WIDTH / width;
1082 new_width = IMAGE_MAX_WIDTH;
1085 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1089 pixbuf_from_stream (TnyStream *stream,
1090 const gchar *mime_type,
1091 guint64 *stream_size,
1092 ModestMsgEditWindow *self)
1094 GdkPixbufLoader *loader;
1097 GError *error = NULL;
1101 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1103 if (loader == NULL) {
1108 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1110 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1112 tny_stream_reset (TNY_STREAM (stream));
1113 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1114 unsigned char read_buffer[128];
1116 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1118 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1121 /* Allow some UI responsiveness */
1122 while (gtk_events_pending ())
1123 gtk_main_iteration ();
1125 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1127 gdk_pixbuf_loader_close (loader, &error);
1130 g_error_free (error);
1131 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1133 g_object_ref (pixbuf);
1134 g_object_unref (loader);
1139 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1140 GdkPixbuf *new_pixbuf;
1142 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1143 gdk_pixbuf_get_width (pixbuf);
1144 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1145 g_object_unref (pixbuf);
1146 pixbuf = new_pixbuf;
1150 *stream_size = size;
1156 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1158 ModestMsgEditWindowPrivate *priv;
1161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1163 g_object_ref (self);
1164 for (iter = tny_list_create_iterator (attachments);
1165 !tny_iterator_is_done (iter);
1166 tny_iterator_next (iter)) {
1167 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1168 const gchar *cid = tny_mime_part_get_content_id (part);
1169 const gchar *mime_type = tny_mime_part_get_content_type (part);
1170 if ((cid != NULL)&&(mime_type != NULL)) {
1171 guint64 stream_size;
1172 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1173 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1176 g_object_unref (stream);
1178 if (pixbuf != NULL) {
1179 priv->images_count ++;
1180 priv->images_size += stream_size;
1181 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1182 g_object_unref (pixbuf);
1185 g_object_unref (part);
1187 g_object_unref (iter);
1188 g_object_unref (self);
1192 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1194 TnyMimePart *parent = NULL;
1195 const gchar *content_type = NULL;
1196 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1198 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1200 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1201 parent = g_object_ref (msg);
1202 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1203 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1206 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1207 iter = tny_list_create_iterator (parts);
1208 while (!tny_iterator_is_done (iter)) {
1210 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1211 content_type = tny_mime_part_get_content_type (part);
1212 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1216 g_object_unref (part);
1218 tny_iterator_next (iter);
1220 g_object_unref (iter);
1221 g_object_unref (parts);
1224 if (parent != NULL) {
1225 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1228 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1229 iter = tny_list_create_iterator (parts);
1230 while (!tny_iterator_is_done (iter)) {
1232 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1233 content_type = tny_mime_part_get_content_type (part);
1234 if (content_type && g_str_has_prefix (content_type, "image/")) {
1235 tny_list_prepend (priv->images, (GObject *) part);
1237 g_object_unref (part);
1238 tny_iterator_next (iter);
1240 g_object_unref (iter);
1241 g_object_unref (parts);
1242 g_object_unref (parent);
1247 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1250 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1252 for (iter = tny_list_create_iterator (attachments) ;
1253 !tny_iterator_is_done (iter);
1254 tny_iterator_next (iter)) {
1255 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1256 const gchar *cid = tny_mime_part_get_content_id (part);
1258 char *invalid = NULL;
1259 gint int_cid = strtol (cid, &invalid, 10);
1260 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1261 priv->next_cid = int_cid + 1;
1264 g_object_unref (part);
1266 g_object_unref (iter);
1270 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1273 gchar *to, *cc, *bcc, *subject;
1275 ModestMsgEditWindowPrivate *priv;
1276 ModestWindowPrivate *parent_priv;
1278 TnyHeaderFlags priority_flags;
1279 TnyFolder *msg_folder;
1280 gboolean is_html = FALSE;
1281 gboolean field_view_set;
1283 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1284 g_return_if_fail (TNY_IS_MSG (msg));
1286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1287 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1289 header = tny_msg_get_header (msg);
1290 to = tny_header_dup_to (header);
1291 cc = tny_header_dup_cc (header);
1292 bcc = tny_header_dup_bcc (header);
1293 subject = tny_header_dup_subject (header);
1295 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1296 priority_flags = tny_header_get_priority (header);
1299 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1301 field_view_set = TRUE;
1303 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1304 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1305 gtk_widget_show (priv->cc_caption);
1306 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1307 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1308 gtk_widget_hide (priv->cc_caption);
1309 field_view_set = FALSE;
1311 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1313 field_view_set = TRUE;
1315 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1316 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1317 gtk_widget_show (priv->bcc_caption);
1318 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1319 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1320 gtk_widget_hide (priv->bcc_caption);
1321 field_view_set = FALSE;
1323 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1327 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1328 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1331 update_window_title (self);
1333 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1334 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1336 if ((body == NULL)||(body[0] == '\0')) {
1338 body = modest_text_utils_convert_to_html ("");
1341 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1342 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1345 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1348 /* Add attachments to the view */
1349 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1350 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1351 if (tny_list_get_length (priv->attachments) == 0) {
1352 gtk_widget_hide (priv->attachments_caption);
1354 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1355 gtk_widget_show_all (priv->attachments_caption);
1357 get_related_images (self, msg);
1358 update_next_cid (self, priv->attachments);
1359 update_next_cid (self, priv->images);
1360 replace_with_images (self, priv->images);
1362 if (preserve_is_rich && !is_html) {
1363 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1364 /* Get the default format required from configuration */
1365 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1366 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1369 /* Set the default focus depending on having already a To: field or not */
1370 if ((!to)||(*to == '\0')) {
1371 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1373 gtk_widget_grab_focus (priv->msg_body);
1376 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1378 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1379 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1381 modest_msg_edit_window_set_modified (self, FALSE);
1383 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1384 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1385 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1386 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1388 if (priv->msg_uid) {
1389 g_free (priv->msg_uid);
1390 priv->msg_uid = NULL;
1393 /* we should set a reference to the incoming message if it is a draft */
1394 msg_folder = tny_msg_get_folder (msg);
1396 if (modest_tny_folder_is_local_folder (msg_folder)) {
1397 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1398 if (type == TNY_FOLDER_TYPE_INVALID)
1399 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1401 if (type == TNY_FOLDER_TYPE_DRAFTS)
1402 priv->draft_msg = g_object_ref(msg);
1403 if (type == TNY_FOLDER_TYPE_OUTBOX)
1404 priv->outbox_msg = g_object_ref(msg);
1405 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1407 g_object_unref (msg_folder);
1418 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1420 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1421 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1422 GtkWidget *placeholder;
1423 GtkWidget *tool_item;
1428 GtkWidget *sizes_menu;
1429 GtkWidget *fonts_menu;
1435 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1436 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1437 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1438 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1440 /* Font color placeholder */
1441 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1442 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1445 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1446 priv->font_color_button = hildon_color_button_new ();
1447 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1448 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1449 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1450 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1451 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1452 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1453 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1454 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1456 G_CALLBACK (modest_msg_edit_window_color_button_change),
1459 /* Font size and face placeholder */
1460 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1461 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1463 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1464 priv->size_tool_button_label = gtk_label_new (NULL);
1465 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1466 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1467 size_text, "</span>", NULL);
1468 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1469 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1471 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1472 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1473 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1474 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1475 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1476 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1477 gtk_widget_set_sensitive (arrow, FALSE);
1478 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1479 sizes_menu = gtk_menu_new ();
1480 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1481 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1484 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1485 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1487 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1491 if (wp_font_size[size_index] == 12)
1492 priv->current_size_index = size_index;
1496 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1497 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1498 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1499 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1500 priv->font_size_toolitem = tool_item;
1503 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1504 priv->font_tool_button_label = gtk_label_new (NULL);
1505 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1506 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1507 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1509 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1510 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1511 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1512 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1513 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1514 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1515 gtk_widget_set_sensitive (arrow, FALSE);
1516 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1517 fonts_menu = gtk_menu_new ();
1518 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1519 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1522 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1524 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1525 0, wp_get_font_name (font_index),
1528 if (font_index == DEFAULT_FONT)
1529 priv->current_face_index = font_index;
1531 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1532 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1533 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1534 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1535 priv->font_face_toolitem = tool_item;
1537 /* Set expand and homogeneous for remaining items */
1538 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1539 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1540 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1541 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
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 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1545 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1546 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1548 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1549 will not show the tool items added to the placeholders) */
1550 gtk_widget_show_all (parent_priv->toolbar);
1552 /* Set the no show all *after* showing all items. We do not
1553 want the toolbar to be shown with a show all because it
1554 could go agains the gconf setting regarding showing or not
1555 the toolbar of the editor window */
1556 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1562 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1565 ModestWindowPrivate *parent_priv;
1566 ModestMsgEditWindowPrivate *priv;
1567 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1568 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1569 ModestWindowMgr *mgr = NULL;
1571 g_return_val_if_fail (msg, NULL);
1572 g_return_val_if_fail (account_name, NULL);
1574 mgr = modest_runtime_get_window_mgr ();
1576 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1579 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1581 /* Menubar. Update the state of some toggles */
1582 priv->from_field_protos = get_transports ();
1583 priv->original_mailbox = NULL;
1584 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1585 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1586 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1587 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1588 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1589 priv->original_mailbox = g_strdup (mailbox);
1590 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1591 /* We set the first mailbox as the active mailbox */
1592 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1593 if (priv->original_mailbox != NULL)
1594 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1595 (gpointer) priv->original_mailbox);
1597 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1598 (gpointer) account_name);
1600 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1602 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1603 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1605 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1606 hildon_touch_selector_get_current_text
1607 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1608 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1609 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1612 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1614 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1616 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1617 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1619 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1621 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1622 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1623 /* Add common dimming rules */
1624 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1625 modest_msg_edit_window_toolbar_dimming_entries,
1626 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1627 MODEST_WINDOW (obj));
1628 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1629 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1630 MODEST_WINDOW (obj));
1631 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1632 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1633 MODEST_WINDOW (obj));
1634 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1635 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1636 MODEST_WINDOW (obj));
1637 /* Insert dimming rules group for this window */
1638 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1639 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1641 /* Setup app menu */
1642 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1644 /* Checks the dimming rules */
1645 g_object_unref (toolbar_rules_group);
1646 g_object_unref (clipboard_rules_group);
1647 gtk_widget_hide (priv->priority_icon);
1648 gtk_widget_queue_resize (priv->subject_box);
1649 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1651 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1653 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1654 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1655 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1656 priv->update_caption_visibility = TRUE;
1658 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1660 /* Track account-removed signal, this window should be closed
1661 in the case we're creating a mail associated to the account
1663 priv->account_removed_handler_id =
1664 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1666 G_CALLBACK(on_account_removed),
1669 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1671 return (ModestWindow*) obj;
1675 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1677 GString **string_buffer = (GString **) user_data;
1679 *string_buffer = g_string_append (*string_buffer, buffer);
1685 * @result: A new string which should be freed with g_free().
1688 get_formatted_data (ModestMsgEditWindow *edit_window)
1690 ModestMsgEditWindowPrivate *priv;
1691 GString *string_buffer = g_string_new ("");
1693 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1695 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1697 modest_text_utils_hyperlinkify (string_buffer);
1699 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1701 return g_string_free (string_buffer, FALSE);
1706 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1709 const gchar *account_name;
1710 ModestMsgEditWindowPrivate *priv;
1711 TnyIterator *att_iter;
1712 const gchar *picker_active_id;
1714 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1718 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1719 g_return_val_if_fail (picker_active_id, NULL);
1720 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1722 /* don't free these (except from) */
1723 data = g_slice_new0 (MsgData);
1724 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1725 data->account_name = g_strdup (account_name);
1726 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1727 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1728 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1729 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1730 data->references = g_strdup (priv->references);
1731 data->in_reply_to = g_strdup (priv->in_reply_to);
1732 if (priv->draft_msg) {
1733 data->draft_msg = g_object_ref (priv->draft_msg);
1734 } else if (priv->outbox_msg) {
1735 data->draft_msg = g_object_ref (priv->outbox_msg);
1737 data->draft_msg = NULL;
1740 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1742 gtk_text_buffer_get_bounds (buf, &b, &e);
1743 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1745 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1746 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1748 data->html_body = NULL;
1750 /* deep-copy the data */
1751 att_iter = tny_list_create_iterator (priv->attachments);
1752 data->attachments = NULL;
1753 while (!tny_iterator_is_done (att_iter)) {
1754 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1755 if (!(TNY_IS_MIME_PART(part))) {
1756 g_warning ("strange data in attachment list");
1757 g_object_unref (part);
1758 tny_iterator_next (att_iter);
1761 data->attachments = g_list_append (data->attachments,
1763 tny_iterator_next (att_iter);
1765 g_object_unref (att_iter);
1767 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1768 att_iter = tny_list_create_iterator (priv->images);
1769 data->images = NULL;
1770 while (!tny_iterator_is_done (att_iter)) {
1771 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1773 if (!(TNY_IS_MIME_PART(part))) {
1774 g_warning ("strange data in attachment list");
1775 g_object_unref (part);
1776 tny_iterator_next (att_iter);
1779 cid = tny_mime_part_get_content_id (part);
1781 gchar *image_tag_id;
1782 GtkTextTag *image_tag;
1784 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1785 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1786 g_free (image_tag_id);
1788 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1790 ((gtk_text_iter_has_tag (&iter, image_tag))||
1791 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1792 data->images = g_list_append (data->images,
1793 g_object_ref (part));
1795 g_object_unref (part);
1796 tny_iterator_next (att_iter);
1798 g_object_unref (att_iter);
1800 data->priority_flags = priv->priority_flags;
1807 unref_gobject (GObject *obj, gpointer data)
1809 if (!G_IS_OBJECT(obj))
1811 g_object_unref (obj);
1815 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1818 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1826 g_free (data->from);
1827 g_free (data->subject);
1828 g_free (data->plain_body);
1829 g_free (data->html_body);
1830 g_free (data->account_name);
1831 g_free (data->references);
1832 g_free (data->in_reply_to);
1834 if (data->draft_msg != NULL) {
1835 g_object_unref (data->draft_msg);
1836 data->draft_msg = NULL;
1839 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1840 g_list_free (data->attachments);
1841 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1842 g_list_free (data->images);
1844 g_slice_free (MsgData, data);
1848 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1850 guint64 *parts_size)
1852 ModestMsgEditWindowPrivate *priv;
1854 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1856 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1858 /* TODO: add images */
1859 *parts_size += priv->images_size;
1860 *parts_count += priv->images_count;
1865 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1868 ModestMsgEditWindowPrivate *priv = NULL;
1869 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1873 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1875 return MODEST_MSG_EDIT_FORMAT_HTML;
1877 return MODEST_MSG_EDIT_FORMAT_TEXT;
1881 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1882 ModestMsgEditFormat format)
1884 ModestMsgEditWindowPrivate *priv;
1886 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1890 case MODEST_MSG_EDIT_FORMAT_HTML:
1891 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1893 case MODEST_MSG_EDIT_FORMAT_TEXT:
1894 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1897 g_return_if_reached ();
1901 ModestMsgEditFormatState *
1902 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1904 ModestMsgEditFormatState *format_state = NULL;
1905 ModestMsgEditWindowPrivate *priv;
1906 WPTextBufferFormat *buffer_format;
1908 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1910 buffer_format = g_new0 (WPTextBufferFormat, 1);
1911 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1913 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1915 format_state = g_new0 (ModestMsgEditFormatState, 1);
1916 format_state->bold = buffer_format->bold&0x1;
1917 format_state->italics = buffer_format->italic&0x1;
1918 format_state->bullet = buffer_format->bullet&0x1;
1919 format_state->color = buffer_format->color;
1920 format_state->font_size = buffer_format->font_size;
1921 format_state->font_family = wp_get_font_name (buffer_format->font);
1922 format_state->justification = buffer_format->justification;
1923 g_free (buffer_format);
1925 return format_state;
1930 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1931 const ModestMsgEditFormatState *format_state)
1933 ModestMsgEditWindowPrivate *priv;
1934 WPTextBufferFormat *buffer_format;
1935 WPTextBufferFormat *current_format;
1937 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1938 g_return_if_fail (format_state != NULL);
1940 buffer_format = g_new0 (WPTextBufferFormat, 1);
1941 current_format = g_new0 (WPTextBufferFormat, 1);
1943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1944 gtk_widget_grab_focus (priv->msg_body);
1945 buffer_format->bold = (format_state->bold != FALSE);
1946 buffer_format->italic = (format_state->italics != FALSE);
1947 buffer_format->color = format_state->color;
1948 buffer_format->font_size = format_state->font_size;
1949 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1950 buffer_format->justification = format_state->justification;
1951 buffer_format->bullet = format_state->bullet;
1953 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1955 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1956 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1957 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1958 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1959 buffer_format->cs.font = (buffer_format->font != current_format->font);
1960 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1961 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1963 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1964 if (buffer_format->cs.bold) {
1965 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1966 GINT_TO_POINTER (buffer_format->bold&0x1));
1968 if (buffer_format->cs.italic) {
1969 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1970 GINT_TO_POINTER (buffer_format->italic&0x1));
1972 if (buffer_format->cs.color) {
1973 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1974 GINT_TO_POINTER (&(buffer_format->color)));
1976 if (buffer_format->cs.font_size) {
1977 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1978 GINT_TO_POINTER (buffer_format->font_size));
1980 if (buffer_format->cs.justification) {
1981 switch (buffer_format->justification) {
1982 case GTK_JUSTIFY_LEFT:
1983 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1984 GINT_TO_POINTER(TRUE));
1986 case GTK_JUSTIFY_CENTER:
1987 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1988 GINT_TO_POINTER(TRUE));
1990 case GTK_JUSTIFY_RIGHT:
1991 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1992 GINT_TO_POINTER(TRUE));
1999 if (buffer_format->cs.font) {
2000 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2001 GINT_TO_POINTER (buffer_format->font));
2003 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2004 if (buffer_format->cs.bullet) {
2005 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2006 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2008 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2010 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2012 g_free (buffer_format);
2013 g_free (current_format);
2015 /* Check dimming rules */
2016 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2017 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2021 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2023 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2025 ModestWindowPrivate *parent_priv;
2026 ModestMsgEditWindowPrivate *priv;
2028 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2031 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2032 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2033 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2034 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2036 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2037 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2038 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2041 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2043 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2044 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2046 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2047 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2049 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2050 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2053 switch (buffer_format->justification)
2055 case GTK_JUSTIFY_LEFT:
2056 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2058 case GTK_JUSTIFY_CENTER:
2059 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2061 case GTK_JUSTIFY_RIGHT:
2062 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2069 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2071 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2072 G_CALLBACK (modest_msg_edit_window_color_button_change),
2074 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2075 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2076 G_CALLBACK (modest_msg_edit_window_color_button_change),
2079 if (priv->current_size_index != buffer_format->font_size) {
2083 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2084 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2088 priv->current_size_index = buffer_format->font_size;
2090 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2091 markup = g_strconcat ("<span font_family='Sans'>",
2092 size_text, "</span>", NULL);
2094 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2098 gtk_tree_path_free (path);
2101 if (priv->current_face_index != buffer_format->font) {
2105 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2106 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2110 priv->current_face_index = buffer_format->font;
2111 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2112 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2113 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2120 g_free (buffer_format);
2124 #ifdef MODEST_HILDON_VERSION_0
2126 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2129 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2130 ModestMsgEditWindowPrivate *priv;
2131 GtkWidget *dialog = NULL;
2133 GdkColor *new_color = NULL;
2135 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2136 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2138 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2139 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2140 g_free (buffer_format);
2142 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2143 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2144 if (new_color != NULL) {
2145 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2146 (gpointer) new_color);
2149 gtk_widget_destroy (dialog);
2154 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2157 ModestMsgEditWindowPrivate *priv;
2158 GtkWidget *dialog = NULL;
2160 GdkColor *old_color = NULL;
2161 const GdkColor *new_color = NULL;
2163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2164 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2166 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2167 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2169 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2170 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2171 if (new_color != NULL)
2172 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2174 gtk_widget_destroy (dialog);
2180 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2183 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2184 ModestMsgEditWindowPrivate *priv;
2185 GtkWidget *dialog = NULL;
2187 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2188 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2190 dialog = hildon_color_chooser_new ();
2191 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2192 g_free (buffer_format);
2194 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2196 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2197 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2200 gtk_widget_destroy (dialog);
2205 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2208 ModestMsgEditWindowPrivate *priv;
2209 GtkWidget *dialog = NULL;
2210 GdkColor *old_color = NULL;
2212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2213 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2215 dialog = hildon_color_chooser_new ();
2216 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2218 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2220 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2221 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2223 gtk_widget_destroy (dialog);
2226 #endif /*!MODEST_HILDON_VERSION_0*/
2231 create_stream_for_uri (const gchar* uri)
2236 TnyStream *result = NULL;
2238 GnomeVFSHandle *handle = NULL;
2239 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2240 if (test == GNOME_VFS_OK) {
2241 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2242 /* Streams over OBEX (Bluetooth) are not seekable but
2243 * we expect them to be (we might need to read them
2244 * several times). So if this is a Bluetooth URI just
2245 * read the whole file into memory (this is not a fast
2246 * protocol so we can assume that these files are not
2247 * going to be very big) */
2248 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2249 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2250 TnyStream *memstream = tny_camel_mem_stream_new ();
2251 tny_stream_write_to_stream (vfssstream, memstream);
2252 g_object_unref (vfssstream);
2255 result = vfssstream;
2263 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2266 ModestMsgEditWindowPrivate *priv;
2267 GtkWidget *dialog = NULL;
2269 GSList *uris = NULL;
2270 GSList *uri_node = NULL;
2272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2274 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2275 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2276 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2278 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2280 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2281 GTK_WINDOW (dialog), GTK_WINDOW (window));
2283 response = gtk_dialog_run (GTK_DIALOG (dialog));
2285 case GTK_RESPONSE_OK:
2287 gchar *current_folder;
2288 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2289 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2290 if (current_folder && current_folder != '\0') {
2292 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2293 current_folder, &err);
2295 g_debug ("Error storing latest used folder: %s", err->message);
2299 g_free (current_folder);
2305 gtk_widget_destroy (dialog);
2307 g_object_ref (window);
2308 /* The operation could take some time so allow the dialog to be closed */
2309 while (gtk_events_pending ())
2310 gtk_main_iteration ();
2312 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2314 GnomeVFSHandle *handle = NULL;
2315 GnomeVFSResult result;
2316 GtkTextIter position;
2317 GtkTextMark *insert_mark;
2319 uri = (const gchar *) uri_node->data;
2320 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2321 if (result == GNOME_VFS_OK) {
2323 GnomeVFSFileInfo *info;
2324 gchar *filename, *basename, *escaped_filename;
2325 TnyMimePart *mime_part;
2327 const gchar *mime_type = NULL;
2328 GnomeVFSURI *vfs_uri;
2329 guint64 stream_size;
2331 gnome_vfs_close (handle);
2332 vfs_uri = gnome_vfs_uri_new (uri);
2334 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2335 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2336 g_free (escaped_filename);
2337 gnome_vfs_uri_unref (vfs_uri);
2338 info = gnome_vfs_file_info_new ();
2340 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2341 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2343 mime_type = gnome_vfs_file_info_get_mime_type (info);
2345 mime_part = tny_platform_factory_new_mime_part
2346 (modest_runtime_get_platform_factory ());
2348 TnyStream *stream = create_stream_for_uri (uri);
2350 if (stream == NULL) {
2352 modest_platform_information_banner (NULL, NULL,
2353 _FM("sfil_ib_opening_not_allowed"));
2355 g_object_unref (mime_part);
2356 gnome_vfs_file_info_unref (info);
2360 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2362 content_id = g_strdup_printf ("%d", priv->next_cid);
2363 tny_mime_part_set_content_id (mime_part, content_id);
2364 g_free (content_id);
2367 basename = g_path_get_basename (filename);
2368 tny_mime_part_set_filename (mime_part, basename);
2371 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2373 if (pixbuf != NULL) {
2374 priv->images_size += stream_size;
2375 priv->images_count ++;
2376 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2377 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2378 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2379 tny_mime_part_get_content_id (mime_part), pixbuf);
2380 g_object_unref (pixbuf);
2382 tny_list_prepend (priv->images, (GObject *) mime_part);
2383 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2385 modest_platform_information_banner (NULL, NULL,
2386 _("mail_ib_file_operation_failed"));
2390 g_object_unref (mime_part);
2391 gnome_vfs_file_info_unref (info);
2395 g_object_unref (window);
2399 on_attach_file_response (GtkDialog *dialog,
2403 GSList *uris = NULL;
2405 GnomeVFSFileSize total_size, allowed_size;
2406 ModestMsgEditWindow *window;
2407 ModestMsgEditWindowPrivate *priv;
2412 case GTK_RESPONSE_OK:
2414 gchar *current_folder;
2416 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2417 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2418 if (current_folder && current_folder != '\0') {
2420 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2421 current_folder, &err);
2423 g_debug ("Error storing latest used folder: %s", err->message);
2427 g_free (current_folder);
2434 window = MODEST_MSG_EDIT_WINDOW (user_data);
2435 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2437 /* allowed size is the maximum size - what's already there */
2438 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2439 &att_num, &att_size);
2440 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2443 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2445 const gchar *uri = (const gchar *) uri_node->data;
2448 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2450 if (total_size > allowed_size) {
2451 g_warning ("%s: total size: %u",
2452 __FUNCTION__, (unsigned int)total_size);
2455 allowed_size -= total_size;
2457 g_slist_foreach (uris, (GFunc) g_free, NULL);
2458 g_slist_free (uris);
2460 gtk_widget_destroy (GTK_WIDGET (dialog));
2464 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2466 GtkWidget *dialog = NULL;
2467 ModestMsgEditWindowPrivate *priv;
2470 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2472 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2474 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2477 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2478 GTK_FILE_CHOOSER_ACTION_OPEN);
2479 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2480 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2481 if (conf_folder && conf_folder[0] != '\0') {
2482 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2485 /* Set the default folder to images folder */
2486 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2487 ".documents", NULL);
2488 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2489 g_free (docs_folder);
2491 g_free (conf_folder);
2492 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2493 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2494 GTK_WINDOW (dialog), GTK_WINDOW (window));
2496 /* Connect to response & show */
2497 g_signal_connect (dialog, "response",
2498 G_CALLBACK (on_attach_file_response), window);
2499 gtk_widget_show (dialog);
2504 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2506 GnomeVFSFileSize allowed_size)
2509 GnomeVFSHandle *handle = NULL;
2510 ModestMsgEditWindowPrivate *priv;
2511 GnomeVFSResult result;
2512 GnomeVFSFileSize size = 0;
2513 g_return_val_if_fail (window, 0);
2514 g_return_val_if_fail (uri, 0);
2516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2518 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2519 if (result == GNOME_VFS_OK) {
2520 TnyMimePart *mime_part;
2522 const gchar *mime_type = NULL;
2524 gchar *escaped_filename;
2527 GnomeVFSFileInfo *info;
2528 GnomeVFSURI *vfs_uri;
2530 gnome_vfs_close (handle);
2531 vfs_uri = gnome_vfs_uri_new (uri);
2534 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2535 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2536 g_free (escaped_filename);
2537 gnome_vfs_uri_unref (vfs_uri);
2539 info = gnome_vfs_file_info_new ();
2541 if (gnome_vfs_get_file_info (uri,
2543 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2545 mime_type = gnome_vfs_file_info_get_mime_type (info);
2546 mime_part = tny_platform_factory_new_mime_part
2547 (modest_runtime_get_platform_factory ());
2549 /* try to get the attachment's size; this may fail for weird
2550 * file systems, like obex, upnp... */
2551 if (allowed_size != 0 &&
2552 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2554 if (size > allowed_size) {
2555 modest_platform_information_banner (NULL, NULL,
2556 _FM("sfil_ib_opening_not_allowed"));
2561 g_warning ("%s: could not get attachment size", __FUNCTION__);
2563 stream = create_stream_for_uri (uri);
2565 if (stream == NULL) {
2567 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2569 g_object_unref (mime_part);
2571 gnome_vfs_file_info_unref (info);
2575 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2576 g_object_unref (stream);
2578 content_id = g_strdup_printf ("%d", priv->next_cid);
2579 tny_mime_part_set_content_id (mime_part, content_id);
2580 g_free (content_id);
2583 basename = g_path_get_basename (filename);
2584 tny_mime_part_set_filename (mime_part, basename);
2587 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2588 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2590 info->size == 0, info->size);
2591 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2592 gtk_widget_show_all (priv->attachments_caption);
2593 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2595 g_object_unref (mime_part);
2596 gnome_vfs_file_info_unref (info);
2603 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2606 ModestMsgEditWindowPrivate *priv;
2609 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2612 if (att_list == NULL) {
2613 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2614 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2615 g_object_unref (att_list);
2620 g_object_ref (att_list);
2623 if (tny_list_get_length (att_list) == 0) {
2624 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2626 gboolean dialog_response;
2627 gchar *message = NULL;
2628 gchar *filename = NULL;
2630 if (tny_list_get_length (att_list) == 1) {
2632 iter = tny_list_create_iterator (att_list);
2633 part = (TnyMimePart *) tny_iterator_get_current (iter);
2634 g_object_unref (iter);
2635 if (TNY_IS_MSG (part)) {
2636 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2638 filename = tny_header_dup_subject (header);
2639 g_object_unref (header);
2641 if (filename == NULL) {
2642 filename = g_strdup (_("mail_va_no_subject"));
2645 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2647 g_object_unref (part);
2649 filename = g_strdup ("");
2651 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2652 "emev_nc_delete_attachments",
2653 tny_list_get_length (att_list)), filename);
2656 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2660 if (dialog_response != GTK_RESPONSE_OK) {
2661 g_object_unref (att_list);
2665 for (iter = tny_list_create_iterator (att_list);
2666 !tny_iterator_is_done (iter);
2667 tny_iterator_next (iter)) {
2668 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2669 const gchar *att_id;
2670 tny_list_remove (priv->attachments, (GObject *) mime_part);
2672 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2674 if (tny_list_get_length (priv->attachments) == 0)
2675 gtk_widget_hide (priv->attachments_caption);
2676 att_id = tny_mime_part_get_content_id (mime_part);
2678 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2680 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2681 g_object_unref (mime_part);
2683 g_object_unref (iter);
2686 g_object_unref (att_list);
2688 /* if the last attachment has been removed, focus the Subject: field */
2689 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2690 gtk_widget_grab_focus (priv->subject_field);
2694 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2697 ModestMsgEditWindowPrivate *priv;
2698 GdkColor *new_color;
2699 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2701 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2702 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2705 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2707 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2709 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2711 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2716 font_size_clicked (GtkToolButton *button,
2717 ModestMsgEditWindow *window)
2719 ModestMsgEditWindowPrivate *priv;
2720 GtkWidget *selector, *dialog;
2722 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2724 selector = hildon_touch_selector_new ();
2725 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2726 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2728 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2729 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2730 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2732 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2736 WPTextBufferFormat format;
2738 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2740 memset (&format, 0, sizeof (format));
2741 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2743 format.cs.font_size = TRUE;
2744 format.cs.text_position = TRUE;
2745 format.cs.font = TRUE;
2746 format.font_size = new_index;
2747 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2749 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2750 GINT_TO_POINTER (new_index)))
2751 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2753 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2754 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2755 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2756 size_text, "</span>", NULL);
2758 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2762 gtk_widget_destroy (dialog);
2764 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2769 font_face_clicked (GtkToolButton *button,
2770 ModestMsgEditWindow *window)
2772 ModestMsgEditWindowPrivate *priv;
2773 GtkWidget *selector, *dialog;
2774 GtkCellRenderer *renderer;
2776 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2778 selector = hildon_touch_selector_new ();
2779 renderer = gtk_cell_renderer_text_new ();
2780 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2781 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2782 renderer, "family", 0, "text", 0, NULL);
2783 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2785 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2786 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2787 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2789 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2790 gint new_font_index;
2794 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2795 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2796 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2800 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2802 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2803 GINT_TO_POINTER(new_font_index)))
2804 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2806 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2807 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2809 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2813 gtk_tree_path_free (path);
2816 gtk_widget_destroy (dialog);
2818 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2823 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2826 ModestMsgEditWindowPrivate *priv = NULL;
2827 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2829 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2830 if (!priv->update_caption_visibility)
2833 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2835 gtk_widget_show (priv->cc_caption);
2837 gtk_widget_hide (priv->cc_caption);
2839 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2843 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2846 ModestMsgEditWindowPrivate *priv = NULL;
2847 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2849 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2850 if (!priv->update_caption_visibility)
2853 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2855 gtk_widget_show (priv->bcc_caption);
2857 gtk_widget_hide (priv->bcc_caption);
2859 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2863 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2864 ModestRecptEditor *editor)
2866 ModestMsgEditWindowPrivate *priv;
2868 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2869 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2871 /* we check for low-mem; in that case, show a warning, and don't allow
2872 * for the addressbook
2874 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2877 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2879 if (editor == NULL) {
2880 GtkWidget *view_focus;
2881 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2883 /* This code should be kept in sync with ModestRecptEditor. The
2884 textview inside the recpt editor is the one that really gets the
2885 focus. As it's inside a scrolled window, and this one inside the
2886 hbox recpt editor inherits from, we'll need to go up in the
2887 hierarchy to know if the text view is part of the recpt editor
2888 or if it's a different text entry */
2890 if (gtk_widget_get_parent (view_focus)) {
2891 GtkWidget *first_parent;
2893 first_parent = gtk_widget_get_parent (view_focus);
2894 if (gtk_widget_get_parent (first_parent) &&
2895 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2896 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2901 editor = MODEST_RECPT_EDITOR (priv->to_field);
2905 modest_address_book_select_addresses (editor);
2910 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2912 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2914 modest_msg_edit_window_open_addressbook (window, NULL);
2918 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2919 gboolean show_toolbar)
2921 ModestWindowPrivate *parent_priv;
2923 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2924 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2926 /* We can not just use the code of
2927 modest_msg_edit_window_setup_toolbar because it has a
2928 mixture of both initialization and creation code. */
2930 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2932 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2936 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2937 TnyHeaderFlags priority_flags)
2939 ModestMsgEditWindowPrivate *priv;
2940 ModestWindowPrivate *parent_priv;
2942 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2944 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2945 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2947 if (priv->priority_flags != priority_flags) {
2948 GtkAction *priority_action = NULL;
2950 priv->priority_flags = priority_flags;
2952 switch (priority_flags) {
2953 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2954 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2955 MODEST_HEADER_ICON_HIGH,
2956 HILDON_ICON_SIZE_SMALL);
2957 gtk_widget_show (priv->priority_icon);
2958 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2959 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2961 case TNY_HEADER_FLAG_LOW_PRIORITY:
2962 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2963 MODEST_HEADER_ICON_LOW,
2964 HILDON_ICON_SIZE_SMALL);
2965 gtk_widget_show (priv->priority_icon);
2966 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2967 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2970 gtk_widget_hide (priv->priority_icon);
2971 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2972 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2975 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2976 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2978 gtk_widget_queue_resize (priv->subject_box);
2982 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2985 ModestMsgEditWindowPrivate *priv;
2986 ModestWindowPrivate *parent_priv;
2987 gint current_format;
2989 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2991 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2994 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2995 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2997 if (current_format != file_format) {
2998 switch (file_format) {
2999 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3000 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3001 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3003 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3007 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3008 response = gtk_dialog_run (GTK_DIALOG (dialog));
3009 gtk_widget_destroy (dialog);
3010 if (response == GTK_RESPONSE_OK) {
3011 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3013 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3014 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3019 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3020 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3021 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3026 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3029 ModestMsgEditWindowPrivate *priv;
3030 WPTextBufferFormat oldfmt, fmt;
3031 gint old_position = 0;
3035 GdkColor *color = NULL;
3036 gboolean bold, bold_set, italic, italic_set;
3037 gboolean underline, underline_set;
3038 gboolean strikethrough, strikethrough_set;
3039 gboolean position_set;
3040 gboolean font_size_set, font_set, color_set;
3043 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3044 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3046 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3047 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3048 GTK_WINDOW(dialog), GTK_WINDOW (window));
3050 /* First we get the currently selected font information */
3051 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3053 switch (oldfmt.text_position) {
3054 case TEXT_POSITION_NORMAL:
3057 case TEXT_POSITION_SUPERSCRIPT:
3065 g_object_set (G_OBJECT (dialog),
3066 "bold", oldfmt.bold != FALSE,
3067 "bold-set", !oldfmt.cs.bold,
3068 "underline", oldfmt.underline != FALSE,
3069 "underline-set", !oldfmt.cs.underline,
3070 "italic", oldfmt.italic != FALSE,
3071 "italic-set", !oldfmt.cs.italic,
3072 "strikethrough", oldfmt.strikethrough != FALSE,
3073 "strikethrough-set", !oldfmt.cs.strikethrough,
3074 "color", &oldfmt.color,
3075 "color-set", !oldfmt.cs.color,
3076 "size", wp_font_size[oldfmt.font_size],
3077 "size-set", !oldfmt.cs.font_size,
3078 "position", old_position,
3079 "position-set", !oldfmt.cs.text_position,
3080 "family", wp_get_font_name (oldfmt.font),
3081 "family-set", !oldfmt.cs.font,
3084 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3085 GTK_WINDOW (dialog), GTK_WINDOW (window));
3086 gtk_widget_show_all (dialog);
3087 priv->font_dialog = dialog;
3088 response = gtk_dialog_run (GTK_DIALOG (dialog));
3089 priv->font_dialog = NULL;
3090 if (response == GTK_RESPONSE_OK) {
3092 g_object_get( dialog,
3094 "bold-set", &bold_set,
3095 "underline", &underline,
3096 "underline-set", &underline_set,
3098 "italic-set", &italic_set,
3099 "strikethrough", &strikethrough,
3100 "strikethrough-set", &strikethrough_set,
3102 "color-set", &color_set,
3104 "size-set", &font_size_set,
3105 "family", &font_name,
3106 "family-set", &font_set,
3107 "position", &position,
3108 "position-set", &position_set,
3113 if (response == GTK_RESPONSE_OK) {
3114 memset(&fmt, 0, sizeof(fmt));
3120 fmt.italic = italic;
3121 fmt.cs.italic = TRUE;
3123 if (underline_set) {
3124 fmt.underline = underline;
3125 fmt.cs.underline = TRUE;
3127 if (strikethrough_set) {
3128 fmt.strikethrough = strikethrough;
3129 fmt.cs.strikethrough = TRUE;
3134 ? TEXT_POSITION_NORMAL
3135 : ( ( position == 1 )
3136 ? TEXT_POSITION_SUPERSCRIPT
3137 : TEXT_POSITION_SUBSCRIPT );
3138 fmt.cs.text_position = TRUE;
3139 fmt.font_size = oldfmt.font_size;
3143 fmt.cs.color = TRUE;
3146 fmt.font = wp_get_font_index(font_name,
3151 if (font_size_set) {
3152 fmt.cs.font_size = TRUE;
3153 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3155 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3156 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3158 gtk_widget_destroy (dialog);
3160 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3164 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3166 ModestMsgEditWindowPrivate *priv;
3168 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3171 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3173 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3174 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3178 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3180 ModestMsgEditWindowPrivate *priv;
3182 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3183 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3185 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3187 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3188 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3193 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3195 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3197 priv->can_undo = can_undo;
3201 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3203 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3205 priv->can_redo = can_redo;
3209 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3211 ModestMsgEditWindowPrivate *priv;
3212 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3215 return priv->can_undo;
3219 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3221 ModestMsgEditWindowPrivate *priv;
3222 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3225 return priv->can_redo;
3230 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3233 GtkTextIter match_start, match_end;
3235 if (image_id == NULL)
3238 gtk_text_buffer_get_start_iter (buffer, &iter);
3240 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3241 GSList *tags = gtk_text_iter_get_tags (&match_start);
3243 for (node = tags; node != NULL; node = g_slist_next (node)) {
3244 GtkTextTag *tag = (GtkTextTag *) node->data;
3245 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3246 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3247 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3249 offset = gtk_text_iter_get_offset (&match_start);
3250 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3251 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3255 gtk_text_iter_forward_char (&iter);
3260 message_is_empty (ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv = NULL;
3264 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3265 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3267 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3268 * so we can ignore markup.
3270 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3273 count = gtk_text_buffer_get_char_count (buf);
3279 msg_body_focus (GtkWidget *focus,
3280 GdkEventFocus *event,
3284 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3285 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3286 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3291 recpt_field_changed (GtkTextBuffer *buffer,
3292 ModestMsgEditWindow *editor)
3294 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3295 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3299 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3301 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3302 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3306 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3309 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3310 GtkTextBuffer *buffer;
3312 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3313 gtk_text_buffer_set_modified (buffer, modified);
3314 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3315 gtk_text_buffer_set_modified (buffer, modified);
3316 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3317 gtk_text_buffer_set_modified (buffer, modified);
3318 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3322 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3324 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3325 const char *account_name;
3326 GtkTextBuffer *buffer;
3328 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3329 if (gtk_text_buffer_get_modified (buffer))
3331 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3332 if (gtk_text_buffer_get_modified (buffer))
3334 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3335 if (gtk_text_buffer_get_modified (buffer))
3337 if (gtk_text_buffer_get_modified (priv->text_buffer))
3340 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3341 if (priv->original_mailbox) {
3342 if (!account_name || strcmp (account_name, priv->original_mailbox))
3344 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3355 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3357 ModestMsgEditWindowPrivate *priv = NULL;
3359 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3360 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3362 /* check if there's no recipient added */
3363 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3364 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3365 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3366 /* no recipient contents, then select contacts */
3367 modest_msg_edit_window_open_addressbook (window, NULL);
3371 g_object_ref (window);
3372 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3373 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3374 g_object_unref (window);
3377 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3378 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3379 g_object_unref (window);
3382 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3383 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3384 g_object_unref (window);
3388 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3389 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3390 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3391 g_object_unref (window);
3398 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3399 ModestMsgEditWindow *window)
3401 modest_msg_edit_window_offer_attach_file (window);
3405 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3407 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3409 return priv->clipboard_text;
3413 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3415 ModestMsgEditWindow *window)
3417 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3418 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3421 /* It could happen that the window was already closed */
3422 if (!GTK_WIDGET_VISIBLE (window))
3425 g_object_ref (window);
3426 text = gtk_clipboard_wait_for_text (selection_clipboard);
3428 if (priv->clipboard_text != NULL) {
3429 g_free (priv->clipboard_text);
3431 priv->clipboard_text = text;
3433 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3435 g_object_unref (window);
3438 static gboolean clipboard_owner_change_idle (gpointer userdata)
3440 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3441 ModestMsgEditWindowPrivate *priv;
3443 gdk_threads_enter ();
3444 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3445 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3447 priv->clipboard_owner_idle = 0;
3448 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3449 gdk_threads_leave ();
3455 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3457 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3458 if (priv->clipboard_owner_idle == 0) {
3459 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3460 clipboard_owner_change_idle,
3461 g_object_ref (window),
3467 subject_field_move_cursor (GtkEntry *entry,
3468 GtkMovementStep step,
3473 /* It could happen that the window was already closed */
3474 if (!GTK_WIDGET_VISIBLE (window))
3477 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3481 update_window_title (ModestMsgEditWindow *window)
3483 ModestMsgEditWindowPrivate *priv = NULL;
3484 const gchar *subject;
3486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3487 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3488 if (subject == NULL || subject[0] == '\0')
3489 subject = _("mail_va_new_email");
3491 gtk_window_set_title (GTK_WINDOW (window), subject);
3497 body_insert_text (GtkTextBuffer *buffer,
3498 GtkTextIter *location,
3501 ModestMsgEditWindow *window)
3503 GtkTextIter end_iter;
3506 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3508 offset = gtk_text_iter_get_offset (&end_iter);
3510 if (offset + len > MAX_BODY_LENGTH) {
3511 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3512 if (offset < MAX_BODY_LENGTH)
3516 /* Prevent endless recursion */
3517 result = g_strndup (text, MAX_BODY_LENGTH - offset);
3518 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3519 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3520 (gpointer) result, (gpointer) MAX_BODY_LENGTH - offset,
3522 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3526 if (offset + len > MAX_BODY_LENGTH) {
3527 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3528 _CS("ckdg_ib_maximum_characters_reached"));
3533 subject_field_changed (GtkEditable *editable,
3534 ModestMsgEditWindow *window)
3536 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3537 update_window_title (window);
3538 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3539 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3540 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3543 subject_field_insert_text (GtkEditable *editable,
3545 gint new_text_length,
3547 ModestMsgEditWindow *window)
3549 GString *result = g_string_new ("");
3551 gint result_len = 0;
3552 const gchar *entry_text = NULL;
3555 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3556 old_length = g_utf8_strlen (entry_text, -1);
3558 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3559 gunichar c = g_utf8_get_char_validated (current, 8);
3560 /* Invalid unichar, stop */
3566 result = g_string_append_unichar (result, c);
3570 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3571 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3574 /* Prevent endless recursion */
3575 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3576 g_signal_emit_by_name (editable, "insert-text",
3577 (gpointer) result->str, (gpointer) result->len,
3578 (gpointer) position, (gpointer) window);
3579 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3583 if (result_len + old_length > 1000) {
3584 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3585 _CS("ckdg_ib_maximum_characters_reached"));
3587 g_string_free (result, TRUE);
3591 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3594 ModestMsgEditWindowPrivate *priv = NULL;
3596 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3599 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3602 gtk_widget_show_all (priv->find_toolbar);
3603 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3605 gtk_widget_hide_all (priv->find_toolbar);
3606 gtk_widget_grab_focus (priv->msg_body);
3611 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3613 GtkTextIter *match_start,
3614 GtkTextIter *match_end)
3616 GtkTextIter end_iter;
3617 gchar *str_casefold;
3620 gchar *range_casefold;
3623 gboolean result = FALSE;
3630 gtk_text_iter_forward_to_end (&end_iter);
3632 str_casefold = g_utf8_casefold (str, -1);
3633 str_chars_n = strlen (str);
3635 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3636 range_casefold = g_utf8_casefold (range_text, -1);
3637 range_chars_n = strlen (range_casefold);
3639 if (range_chars_n < str_chars_n) {
3640 g_free (str_casefold);
3641 g_free (range_text);
3642 g_free (range_casefold);
3646 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3647 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3648 if (!g_utf8_collate (range_subtext, str_casefold)) {
3649 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3651 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3652 match_start, match_end, NULL)) {
3653 g_warning ("Matched string with collate, but not matched in model");
3655 g_free (found_text);
3657 g_free (range_subtext);
3661 g_free (str_casefold);
3662 g_free (range_text);
3663 g_free (range_casefold);
3670 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3671 ModestMsgEditWindow *window)
3673 gchar *current_search = NULL;
3674 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3676 GtkTextIter selection_start, selection_end;
3677 GtkTextIter match_start, match_end;
3678 gboolean continue_search = FALSE;
3680 if (message_is_empty (window)) {
3681 g_free (priv->last_search);
3682 priv->last_search = NULL;
3683 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3687 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3688 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3689 g_free (current_search);
3690 g_free (priv->last_search);
3691 priv->last_search = NULL;
3692 /* Information banner about empty search */
3693 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3697 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3698 continue_search = TRUE;
3700 g_free (priv->last_search);
3701 priv->last_search = g_strdup (current_search);
3704 if (continue_search) {
3705 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3706 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3707 &match_start, &match_end);
3709 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3711 GtkTextIter buffer_start;
3712 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3713 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3714 &match_start, &match_end);
3716 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3719 /* Mark as selected the string found in search */
3721 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3722 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3723 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3725 g_free (priv->last_search);
3726 priv->last_search = NULL;
3728 g_free (current_search);
3732 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3734 ModestMsgEditWindowPrivate *priv;
3736 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3741 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3744 ModestMsgEditWindowPrivate *priv;
3746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3751 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3752 ModestMsgEditWindow *window)
3754 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3758 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3761 ModestMsgEditWindowPrivate *priv;
3762 TnyHeader *header = NULL;
3764 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3765 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3767 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3769 if (priv->draft_msg != NULL) {
3770 g_object_unref (priv->draft_msg);
3773 if (draft != NULL) {
3774 g_object_ref (draft);
3775 header = tny_msg_get_header (draft);
3776 if (priv->msg_uid) {
3777 g_free (priv->msg_uid);
3778 priv->msg_uid = NULL;
3780 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3783 priv->draft_msg = draft;
3787 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3788 GtkTextIter *start, GtkTextIter *end,
3791 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3792 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3795 if (tag == NULL) return;
3796 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3797 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3798 replace_with_images (window, priv->images);
3803 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3806 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3808 g_return_if_fail (TNY_IS_MIME_PART (part));
3809 tny_list_prepend (priv->attachments, (GObject *) part);
3810 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3811 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3812 gtk_widget_show_all (priv->attachments_caption);
3813 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3817 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3819 ModestMsgEditWindowPrivate *priv;
3821 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3824 return priv->msg_uid;
3828 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3829 ModestMsgEditWindowWidgetType widget_type)
3831 ModestMsgEditWindowPrivate *priv;
3833 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3834 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3836 switch (widget_type) {
3837 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3838 return priv->msg_body;
3840 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3841 return priv->to_field;
3843 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3844 return priv->cc_field;
3846 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3847 return priv->bcc_field;
3849 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3850 return priv->subject_field;
3852 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3853 return priv->attachments_view;
3861 remove_tags (WPTextBuffer *buffer)
3863 GtkTextIter start, end;
3865 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3866 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3868 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3872 on_account_removed (TnyAccountStore *account_store,
3873 TnyAccount *account,
3876 /* Do nothing if it's a store account, because we use the
3877 transport to send the messages */
3878 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3879 const gchar *parent_acc = NULL;
3880 const gchar *our_acc = NULL;
3882 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3883 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3884 /* Close this window if I'm showing a message of the removed account */
3885 if (strcmp (parent_acc, our_acc) == 0)
3886 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3890 static void update_signature (ModestMsgEditWindow *self,
3891 const gchar *old_account,
3892 const gchar *new_account)
3894 ModestMsgEditWindowPrivate *priv;
3895 gboolean has_old_signature, has_new_signature;
3897 GtkTextIter match_start, match_end;
3898 ModestAccountMgr *mgr;
3900 gchar *full_signature;
3902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3904 gtk_text_buffer_begin_user_action (priv->text_buffer);
3906 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3907 mgr = modest_runtime_get_account_mgr ();
3911 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3912 if (has_old_signature) {
3913 full_signature = g_strconcat ("\n--\n", signature, NULL);
3914 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3915 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3917 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3918 &match_start, &match_end, NULL)) {
3921 g_free (full_signature);
3926 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3927 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3928 if (has_new_signature) {
3929 full_signature = g_strconcat ("\n--\n", signature, NULL);
3930 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
3931 g_free (full_signature);
3934 gtk_text_buffer_end_user_action (priv->text_buffer);
3938 from_field_changed (HildonPickerButton *button,
3939 ModestMsgEditWindow *self)
3941 ModestMsgEditWindowPrivate *priv;
3942 gchar *old_account, *new_account;
3944 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3946 old_account = priv->last_from_account;
3947 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3948 new_account = priv->last_from_account;
3950 update_signature (self, old_account, new_account);
3954 typedef struct _MessageSettingsHelper {
3955 ModestMsgEditWindow *window;
3956 GSList *priority_group;
3957 GSList *format_group;
3958 GtkToggleButton *current_priority;
3959 GtkToggleButton *current_format;
3960 } MessageSettingsHelper;
3963 on_priority_toggle (GtkToggleButton *button,
3964 MessageSettingsHelper *helper)
3967 ModestMsgEditWindowPrivate *priv;
3969 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
3970 if (gtk_toggle_button_get_active (button)) {
3972 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3973 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3974 if ((node_button != button) &&
3975 gtk_toggle_button_get_active (node_button)) {
3976 gtk_toggle_button_set_active (node_button, FALSE);
3979 helper->current_priority = button;
3981 gboolean found = FALSE;
3982 /* If no one is active, activate it again */
3983 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
3984 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
3985 if (gtk_toggle_button_get_active (node_button)) {
3991 gtk_toggle_button_set_active (button, TRUE);
3997 on_format_toggle (GtkToggleButton *button,
3998 MessageSettingsHelper *helper)
4001 ModestMsgEditWindowPrivate *priv;
4003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4004 if (gtk_toggle_button_get_active (button)) {
4006 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4007 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4008 if ((node_button != button) &&
4009 gtk_toggle_button_get_active (node_button)) {
4010 gtk_toggle_button_set_active (node_button, FALSE);
4013 helper->current_format = button;
4015 gboolean found = FALSE;
4016 /* If no one is active, activate it again */
4017 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4018 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4019 if (gtk_toggle_button_get_active (node_button)) {
4025 gtk_toggle_button_set_active (button, TRUE);
4032 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4037 GtkWidget *priority_hbox;
4038 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4039 GtkWidget *captioned;
4040 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4041 GtkWidget *format_hbox;
4042 GtkWidget *html_toggle, *text_toggle;
4043 ModestMsgEditWindowPrivate *priv;
4044 MessageSettingsHelper helper = {0,};
4046 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4047 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4048 helper.window = window;
4049 helper.priority_group = NULL;
4050 helper.format_group = NULL;
4052 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4053 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4055 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4056 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4057 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4058 vbox = gtk_vbox_new (FALSE, 0);
4059 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4060 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4061 gtk_container_add (GTK_CONTAINER (align), vbox);
4062 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4063 gtk_widget_show (align);
4064 gtk_widget_show (vbox);
4066 /* Priority toggles */
4067 priority_hbox = gtk_hbox_new (TRUE, 0);
4068 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4069 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4070 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4071 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4072 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4073 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4074 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4075 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4076 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4077 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4078 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4079 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4080 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4081 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4082 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4083 gtk_widget_show_all (priority_hbox);
4084 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4085 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4086 gtk_widget_show (captioned);
4087 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4089 /* format toggles */
4090 format_hbox = gtk_hbox_new (TRUE, 0);
4091 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4092 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4093 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4094 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4095 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4096 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4097 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4098 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4099 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4100 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4101 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4102 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4103 gtk_widget_show_all (format_hbox);
4104 gtk_widget_show (format_hbox);
4105 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4108 g_object_unref (title_sizegroup);
4109 g_object_unref (value_sizegroup);
4111 /* Set current values */
4112 switch (priv->priority_flags) {
4113 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4114 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4115 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4117 case TNY_HEADER_FLAG_LOW_PRIORITY:
4118 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4119 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4122 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4123 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4127 switch (modest_msg_edit_window_get_format (window)) {
4128 case MODEST_MSG_EDIT_FORMAT_TEXT:
4129 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4130 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4132 case MODEST_MSG_EDIT_FORMAT_HTML:
4134 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4135 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4139 /* Signal connects */
4140 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4141 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4142 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4143 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4144 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4146 /* Save settings if the user clicked on done */
4147 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4148 TnyHeaderFlags flags;
4149 ModestMsgEditFormat old_format, new_format;
4151 /* Set priority flags */
4152 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4153 if (priv->priority_flags != flags)
4154 modest_msg_edit_window_set_priority_flags (window, flags);
4156 /* Set edit format */
4157 old_format = modest_msg_edit_window_get_format (window);
4158 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4159 if (old_format != new_format) {
4160 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4161 modest_msg_edit_window_set_file_format (window, file_format);
4165 gtk_widget_destroy (dialog);
4166 g_slist_free (helper.priority_group);
4170 on_message_settings (GtkAction *action,
4171 ModestMsgEditWindow *window)
4173 modest_msg_edit_window_show_msg_settings_dialog (window);
4177 on_cc_button_toggled (HildonCheckButton *button,
4178 ModestMsgEditWindow *window)
4180 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4182 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4183 hildon_check_button_get_active (button));
4187 on_bcc_button_toggled (HildonCheckButton *button,
4188 ModestMsgEditWindow *window)
4190 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4192 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4193 hildon_check_button_get_active (button));
4197 setup_menu (ModestMsgEditWindow *self)
4199 ModestMsgEditWindowPrivate *priv = NULL;
4201 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4205 /* Settings menu buttons */
4206 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4207 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4209 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4210 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4211 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4213 priv->cc_button = hildon_check_button_new (0);
4214 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4215 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4217 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4219 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4220 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4221 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4222 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4224 priv->bcc_button = hildon_check_button_new (0);
4225 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4226 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4228 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4230 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4231 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4232 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4233 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4235 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4236 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4237 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4238 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("TODO: add attachment"), NULL,
4239 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4241 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4242 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4243 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4244 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4245 APP_MENU_CALLBACK (on_message_settings),
4247 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4248 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4253 emit_open_addressbook (GtkButton *button,
4254 ModestRecptEditor *editor)
4256 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4260 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4261 const gchar *label, GtkWidget *control)
4263 GtkWidget *abook_button;
4266 GtkWidget *label_widget;
4268 box = gtk_hbox_new (FALSE, 0);
4270 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4271 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4273 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4274 label_widget = gtk_label_new (label);
4275 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4276 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4278 gtk_container_add (GTK_CONTAINER (align), abook_button);
4279 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4280 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4281 if (title_size_group)
4282 gtk_size_group_add_widget (title_size_group, label_widget);
4283 if (value_size_group)
4284 gtk_size_group_add_widget (value_size_group, control);
4286 g_signal_connect (G_OBJECT (abook_button), "clicked",
4287 G_CALLBACK (emit_open_addressbook), control);