1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static void update_branding (ModestMsgEditWindow *self,
191 const gchar *new_account);
192 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
193 const gchar *label, GtkWidget *control);
194 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
195 static void DEBUG_BUFFER (WPTextBuffer *buffer)
199 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
201 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
202 while (!gtk_text_iter_is_end (&iter)) {
203 GString *output = g_string_new ("");
204 GSList *toggled_tags;
207 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
208 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
209 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
210 GtkTextTag *tag = (GtkTextTag *) node->data;
212 g_object_get (G_OBJECT (tag), "name", &name, NULL);
213 output = g_string_append (output, name);
214 g_string_append (output, " ");
216 output = g_string_append (output, "] OPENED [ ");
217 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
218 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
219 GtkTextTag *tag = (GtkTextTag *) node->data;
221 g_object_get (G_OBJECT (tag), "name", &name, NULL);
222 output = g_string_append (output, name);
223 g_string_append (output, " ");
225 output = g_string_append (output, "]\n");
226 g_debug ("%s", output->str);
227 g_string_free (output, TRUE);
228 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
230 g_debug ("END BUFFER");
234 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
235 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
239 /* static gboolean */
240 /* on_key_pressed (GtkWidget *self, */
241 /* GdkEventKey *event, */
242 /* gpointer user_data); */
244 /* list my signals */
251 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
252 struct _ModestMsgEditWindowPrivate {
254 GtkWidget *header_box;
256 ModestPairList *from_field_protos;
257 GtkWidget *from_field;
258 gchar *last_from_account;
259 gchar *original_account_name;
264 gchar *original_mailbox;
268 GtkWidget *bcc_field;
269 GtkWidget *subject_field;
270 GtkWidget *attachments_view;
271 GtkWidget *priority_icon;
272 GtkWidget *subject_box;
273 GtkWidget *send_button;
275 GtkWidget *cc_caption;
276 GtkWidget *bcc_caption;
277 gboolean update_caption_visibility;
278 GtkWidget *attachments_caption;
280 GtkTextBuffer *text_buffer;
282 GtkWidget *font_size_toolitem;
283 GtkWidget *font_face_toolitem;
284 GtkWidget *font_color_button;
285 GtkWidget *font_color_toolitem;
286 GSList *font_items_group;
287 GtkTreeModel *faces_model;
288 gint current_face_index;
289 GtkWidget *font_tool_button_label;
290 GtkTreeModel *sizes_model;
291 gint current_size_index;
292 GtkWidget *size_tool_button_label;
294 GtkWidget *find_toolbar;
297 GtkWidget *font_dialog;
300 guint correct_scroll_idle;
301 guint scroll_drag_timeout_id;
305 TnyList *attachments;
310 TnyHeaderFlags priority_flags;
312 gboolean can_undo, can_redo;
313 gulong clipboard_change_handler_id;
314 gulong default_clipboard_change_handler_id;
315 gulong account_removed_handler_id;
316 guint clipboard_owner_idle;
317 gchar *clipboard_text;
326 GtkWidget *cc_button;
327 GtkWidget *bcc_button;
329 GtkWidget *max_chars_banner;
331 GtkWidget *brand_icon;
332 GtkWidget *brand_label;
333 GtkWidget *brand_container;
336 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
337 MODEST_TYPE_MSG_EDIT_WINDOW, \
338 ModestMsgEditWindowPrivate))
340 static GtkWindowClass *parent_class = NULL;
342 /* uncomment the following if you have defined any signals */
343 /* static guint signals[LAST_SIGNAL] = {0}; */
346 modest_msg_edit_window_get_type (void)
348 static GType my_type = 0;
350 static const GTypeInfo my_info = {
351 sizeof(ModestMsgEditWindowClass),
352 NULL, /* base init */
353 NULL, /* base finalize */
354 (GClassInitFunc) modest_msg_edit_window_class_init,
355 NULL, /* class finalize */
356 NULL, /* class data */
357 sizeof(ModestMsgEditWindow),
359 (GInstanceInitFunc) modest_msg_edit_window_init,
362 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
363 "ModestMsgEditWindow",
371 save_state (ModestWindow *self)
373 modest_widget_memory_save (modest_runtime_get_conf(),
374 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
379 restore_settings (ModestMsgEditWindow *self)
381 ModestConf *conf = NULL;
383 conf = modest_runtime_get_conf ();
385 /* Dim at start clipboard actions */
386 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
391 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
393 GObjectClass *gobject_class;
394 ModestWindowClass *modest_window_class;
395 gobject_class = (GObjectClass*) klass;
396 modest_window_class = (ModestWindowClass*) klass;
398 parent_class = g_type_class_peek_parent (klass);
399 gobject_class->finalize = modest_msg_edit_window_finalize;
401 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
402 modest_window_class->save_state_func = save_state;
403 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
405 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
409 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
411 ModestMsgEditWindowPrivate *priv;
412 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
414 priv->msg_body = NULL;
415 priv->from_field = NULL;
416 priv->to_field = NULL;
417 priv->cc_field = NULL;
418 priv->bcc_field = NULL;
419 priv->subject_field = NULL;
420 priv->attachments = TNY_LIST (tny_simple_list_new ());
421 priv->images = TNY_LIST (tny_simple_list_new ());
422 priv->images_size = 0;
423 priv->images_count = 0;
426 priv->cc_caption = NULL;
427 priv->bcc_caption = NULL;
428 priv->update_caption_visibility = FALSE;
430 priv->priority_flags = 0;
432 priv->find_toolbar = NULL;
433 priv->last_search = NULL;
435 priv->draft_msg = NULL;
436 priv->outbox_msg = NULL;
437 priv->msg_uid = NULL;
439 priv->can_undo = FALSE;
440 priv->can_redo = FALSE;
441 priv->clipboard_change_handler_id = 0;
442 priv->default_clipboard_change_handler_id = 0;
443 priv->account_removed_handler_id = 0;
444 priv->clipboard_owner_idle = 0;
445 priv->clipboard_text = NULL;
448 priv->scroll_drag_timeout_id = 0;
449 priv->correct_scroll_idle = 0;
450 priv->last_upper = 0.0;
452 priv->font_dialog = NULL;
453 priv->app_menu = NULL;
455 priv->references = NULL;
456 priv->in_reply_to = NULL;
457 priv->max_chars_banner = NULL;
459 if (!is_wp_text_buffer_started) {
460 is_wp_text_buffer_started = TRUE;
461 wp_text_buffer_library_init ();
466 hildon_program_add_window (hildon_program_get_instance(),
471 multimailbox_get_default_mailbox (const gchar *account_name)
473 gchar *transport_account;
474 gchar *result = NULL;
476 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
478 TNY_ACCOUNT_TYPE_TRANSPORT);
479 if (transport_account) {
481 ModestProtocolRegistry *registry;
483 registry = modest_runtime_get_protocol_registry ();
485 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
486 MODEST_ACCOUNT_PROTO, TRUE);
488 ModestProtocol *protocol =
489 modest_protocol_registry_get_protocol_by_name (registry,
490 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
492 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
493 ModestPairList *pair_list;
495 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
498 ModestPair *pair = (ModestPair *) pair_list->data;
499 result = g_strdup ((const gchar *) pair->first);
500 modest_pair_list_free (pair_list);
511 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
513 static ModestPairList*
514 get_transports (void)
516 GSList *transports = NULL;
518 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
519 GSList *accounts = modest_account_mgr_account_names (account_mgr,
520 TRUE /* only enabled accounts. */);
522 GSList *cursor = accounts;
524 gchar *account_name = cursor->data;
527 gchar *transport_account;
528 gboolean multi_mailbox = FALSE;
529 ModestProtocol *protocol = NULL;
531 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
533 transport_account = modest_account_mgr_get_server_account_name
534 (modest_runtime_get_account_mgr (),
536 TNY_ACCOUNT_TYPE_TRANSPORT);
537 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
538 ModestPairList *pair_list;
539 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
542 transports = g_slist_concat (transports, pair_list);
543 multi_mailbox = TRUE;
548 if (!multi_mailbox) {
549 gchar *from_string = NULL;
551 from_string = modest_account_mgr_get_from_string (account_mgr,
553 if (from_string && account_name) {
554 gchar *name = account_name;
555 ModestPair *pair = modest_pair_new ((gpointer) name,
556 (gpointer) from_string , TRUE);
557 transports = g_slist_prepend (transports, pair);
562 cursor = cursor->next;
564 g_slist_free (accounts); /* only free the accounts, not the elements,
565 * because they are used in the pairlist */
569 static void window_focus (GtkWindow *window,
573 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
577 scroll_drag_timeout (gpointer userdata)
579 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
580 ModestMsgEditWindowPrivate *priv;
582 /* It could happen that the window was already closed */
583 if (!GTK_WIDGET_VISIBLE (win))
586 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
588 correct_scroll_without_drag_check (win, TRUE);
590 priv->scroll_drag_timeout_id = 0;
596 correct_scroll_without_drag_check_idle (gpointer userdata)
598 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
599 ModestMsgEditWindowPrivate *priv;
601 GdkRectangle rectangle;
602 gint offset_min, offset_max;
606 /* It could happen that the window was already closed */
607 if (!GTK_WIDGET_VISIBLE (w))
610 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
612 insert = gtk_text_buffer_get_insert (priv->text_buffer);
613 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
615 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
616 offset_min = priv->msg_body->allocation.y + rectangle.y;
617 offset_max = offset_min + rectangle.height;
619 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
620 offset_min = MAX (offset_min - 48, 0);
621 offset_max = MIN (offset_max + 48, vadj->upper);
623 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
625 priv->correct_scroll_idle = 0;
630 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
632 ModestMsgEditWindowPrivate *priv;
634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
636 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
639 if (priv->correct_scroll_idle > 0) {
643 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
644 (GSourceFunc) correct_scroll_without_drag_check_idle,
650 correct_scroll (ModestMsgEditWindow *w)
652 ModestMsgEditWindowPrivate *priv;
654 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
655 if (gtk_grab_get_current () == priv->msg_body) {
656 if (priv->scroll_drag_timeout_id == 0) {
657 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
659 (GSourceFunc) scroll_drag_timeout,
666 correct_scroll_without_drag_check (w, TRUE);
670 text_buffer_end_user_action (GtkTextBuffer *buffer,
671 ModestMsgEditWindow *userdata)
674 correct_scroll (userdata);
678 text_buffer_mark_set (GtkTextBuffer *buffer,
681 ModestMsgEditWindow *userdata)
683 gtk_text_buffer_begin_user_action (buffer);
684 gtk_text_buffer_end_user_action (buffer);
688 cut_clipboard_check (GtkTextView *text_view,
691 GtkTextBuffer *buffer;
693 buffer = gtk_text_view_get_buffer (text_view);
694 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
695 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
700 copy_clipboard_check (GtkTextView *text_view,
703 GtkTextBuffer *buffer;
705 buffer = gtk_text_view_get_buffer (text_view);
706 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
707 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
712 attachment_deleted (ModestAttachmentsView *attachments_view,
715 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
720 connect_signals (ModestMsgEditWindow *obj)
722 ModestMsgEditWindowPrivate *priv;
724 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
726 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
727 G_CALLBACK (text_buffer_refresh_attributes), obj);
728 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
729 G_CALLBACK (text_buffer_can_undo), obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
731 G_CALLBACK (text_buffer_can_redo), obj);
732 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
733 G_CALLBACK (body_changed), obj);
734 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
735 G_CALLBACK (body_insert_text), obj);
736 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
737 G_CALLBACK (body_changed), obj);
738 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
739 G_CALLBACK (text_buffer_end_user_action), obj);
740 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
741 G_CALLBACK (text_buffer_mark_set), obj);
742 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
743 G_CALLBACK (text_buffer_apply_tag), obj);
744 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
745 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
746 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
747 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
748 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
749 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
751 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
752 G_CALLBACK (modest_ui_actions_on_send), obj);
754 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
755 G_CALLBACK (from_field_changed), obj);
757 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
758 G_CALLBACK (msg_body_focus), obj);
759 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
760 G_CALLBACK (msg_body_focus), obj);
761 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
762 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
763 "changed", G_CALLBACK (recpt_field_changed), obj);
764 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
765 "changed", G_CALLBACK (recpt_field_changed), obj);
766 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
767 "changed", G_CALLBACK (recpt_field_changed), obj);
768 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
769 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
770 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
772 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
773 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
775 priv->clipboard_change_handler_id =
776 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
777 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
778 priv->default_clipboard_change_handler_id =
779 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
780 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
782 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
783 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
784 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
788 init_wp_text_view_style ()
790 static gboolean initialized = FALSE;
793 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
799 init_window (ModestMsgEditWindow *obj)
801 GtkWidget *to_caption, *subject_caption;
802 GtkWidget *main_vbox;
803 ModestMsgEditWindowPrivate *priv;
804 GtkActionGroup *action_group;
805 ModestWindowPrivate *parent_priv;
806 GdkPixbuf *window_icon = NULL;
807 GError *error = NULL;
809 GtkSizeGroup *title_size_group;
810 GtkSizeGroup *value_size_group;
811 GtkWidget *window_box;
812 GtkWidget *window_align;
813 #if (GTK_MINOR_VERSION >= 10)
814 GdkAtom deserialize_type;
816 GtkWidget *from_send_hbox;
817 GtkWidget *send_icon;
818 GtkWidget *attachments_label;
819 GtkWidget *branding_box;
821 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
822 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
824 parent_priv->ui_manager = gtk_ui_manager_new();
825 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
826 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
828 /* Add common actions */
829 gtk_action_group_add_actions (action_group,
830 modest_msg_edit_action_entries,
831 G_N_ELEMENTS (modest_msg_edit_action_entries),
833 gtk_action_group_add_actions (action_group,
834 hildon2_msg_edit_action_entries,
835 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
837 gtk_action_group_add_toggle_actions (action_group,
838 modest_msg_edit_toggle_action_entries,
839 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
841 gtk_action_group_add_radio_actions (action_group,
842 modest_msg_edit_alignment_radio_action_entries,
843 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
845 G_CALLBACK (modest_ui_actions_on_change_justify),
847 gtk_action_group_add_radio_actions (action_group,
848 modest_msg_edit_priority_action_entries,
849 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
851 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
853 gtk_action_group_add_radio_actions (action_group,
854 modest_msg_edit_file_format_action_entries,
855 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
856 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
857 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
859 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
860 g_object_unref (action_group);
862 /* Load the UI definition */
863 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
866 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
867 g_clear_error (&error);
870 /* Add accelerators */
871 gtk_window_add_accel_group (GTK_WINDOW (obj),
872 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
874 parent_priv->menubar = NULL;
876 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
877 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
879 /* Note: This ModestPairList* must exist for as long as the picker
880 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
881 * so it can't know how to manage its memory. */
882 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
883 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
885 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
886 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
887 _("mail_va_from"), priv->from_field);
888 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
889 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
890 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
892 priv->to_field = modest_recpt_editor_new ();
893 priv->cc_field = modest_recpt_editor_new ();
894 priv->bcc_field = modest_recpt_editor_new ();
895 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
896 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
897 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
898 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
899 priv->priority_icon = gtk_image_new ();
900 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
901 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
902 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
903 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
904 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
905 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
906 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
907 priv->attachments_view = modest_attachments_view_new (NULL);
908 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
909 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
911 priv->header_box = gtk_vbox_new (FALSE, 0);
913 to_caption = _create_addressbook_box
914 (title_size_group, value_size_group,
915 _("mail_va_to"), priv->to_field);
916 priv->cc_caption = _create_addressbook_box
917 (title_size_group, value_size_group,
918 _("mail_va_cc"), priv->cc_field);
919 priv->bcc_caption = _create_addressbook_box
920 (title_size_group, value_size_group,
921 _("mail_va_hotfix1"), priv->bcc_field);
922 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
923 _("mail_va_subject"), FALSE, priv->subject_box);
924 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
925 _("mail_va_attachment"),
927 priv->attachments_view,
928 HILDON_SIZE_AUTO_WIDTH |
929 HILDON_SIZE_AUTO_HEIGHT);
930 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
931 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
934 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
935 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
936 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
937 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
939 g_object_unref (title_size_group);
940 g_object_unref (value_size_group);
942 priv->brand_icon = gtk_image_new ();
943 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
944 priv->brand_label = gtk_label_new (NULL);
945 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
946 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
947 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
948 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
950 from_send_hbox = gtk_hbox_new (FALSE, 0);
951 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
952 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
954 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
955 gtk_widget_show (branding_box);
956 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
957 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
959 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
960 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
961 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
962 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
965 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
966 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
967 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
968 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
969 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
970 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
971 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
972 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
974 init_wp_text_view_style ();
976 priv->msg_body = modest_wp_text_view_new ();
979 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
980 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
981 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
982 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
983 #if (GTK_MINOR_VERSION >= 10)
984 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
985 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
987 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
988 deserialize_type, TRUE);
990 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
992 priv->find_toolbar = hildon_find_toolbar_new (NULL);
993 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
995 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
997 priv->pannable = hildon_pannable_area_new ();
999 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1001 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1002 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1003 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1005 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1006 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1007 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1009 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1010 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1012 window_box = gtk_vbox_new (FALSE, 0);
1013 gtk_container_add (GTK_CONTAINER(obj), window_box);
1015 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1017 /* Set window icon */
1018 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1020 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1021 g_object_unref (window_icon);
1026 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1028 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1030 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1031 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1032 priv->clipboard_change_handler_id))
1033 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1034 priv->clipboard_change_handler_id);
1035 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1036 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1037 priv->default_clipboard_change_handler_id))
1038 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1039 priv->default_clipboard_change_handler_id);
1041 if (priv->account_removed_handler_id &&
1042 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1043 priv->account_removed_handler_id))
1044 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1045 priv->account_removed_handler_id);
1049 modest_msg_edit_window_finalize (GObject *obj)
1051 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1053 if (priv->max_chars_banner) {
1054 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1055 priv->max_chars_banner = FALSE;
1058 /* Sanity check: shouldn't be needed, the window mgr should
1059 call this function before */
1060 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1062 if (priv->font_dialog != NULL) {
1063 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1066 if (priv->clipboard_text != NULL) {
1067 g_free (priv->clipboard_text);
1068 priv->clipboard_text = NULL;
1071 if (priv->draft_msg != NULL) {
1072 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1073 if (TNY_IS_HEADER (header)) {
1074 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1075 modest_window_mgr_unregister_header (mgr, header);
1077 g_object_unref (priv->draft_msg);
1078 priv->draft_msg = NULL;
1080 if (priv->outbox_msg != NULL) {
1081 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1082 if (TNY_IS_HEADER (header)) {
1083 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1084 modest_window_mgr_unregister_header (mgr, header);
1086 g_object_unref (priv->outbox_msg);
1087 priv->outbox_msg = NULL;
1089 if (priv->correct_scroll_idle > 0) {
1090 g_source_remove (priv->correct_scroll_idle);
1091 priv->correct_scroll_idle = 0;
1093 if (priv->scroll_drag_timeout_id > 0) {
1094 g_source_remove (priv->scroll_drag_timeout_id);
1095 priv->scroll_drag_timeout_id = 0;
1097 if (priv->clipboard_owner_idle > 0) {
1098 g_source_remove (priv->clipboard_owner_idle);
1099 priv->clipboard_owner_idle = 0;
1101 if (priv->original_account_name)
1102 g_free (priv->original_account_name);
1103 if (priv->original_mailbox)
1104 g_free (priv->original_mailbox);
1105 g_free (priv->msg_uid);
1106 g_free (priv->last_search);
1107 g_free (priv->references);
1108 g_free (priv->in_reply_to);
1109 g_object_unref (priv->attachments);
1110 g_object_unref (priv->images);
1112 /* This had to stay alive for as long as the picker that used it: */
1113 modest_pair_list_free (priv->from_field_protos);
1115 G_OBJECT_CLASS(parent_class)->finalize (obj);
1119 pixbuf_size_prepared (GdkPixbufLoader *loader,
1122 ModestMsgEditWindow *self)
1124 gint new_height, new_width;
1127 new_height = height;
1131 if (width > IMAGE_MAX_WIDTH) {
1132 new_height = height * IMAGE_MAX_WIDTH / width;
1133 new_width = IMAGE_MAX_WIDTH;
1136 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1140 pixbuf_from_stream (TnyStream *stream,
1141 const gchar *mime_type,
1142 guint64 *stream_size,
1143 ModestMsgEditWindow *self)
1145 GdkPixbufLoader *loader;
1148 GError *error = NULL;
1152 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1154 if (loader == NULL) {
1159 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1161 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1163 tny_stream_reset (TNY_STREAM (stream));
1164 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1165 unsigned char read_buffer[128];
1167 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1169 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1172 /* Allow some UI responsiveness */
1173 while (gtk_events_pending ())
1174 gtk_main_iteration ();
1176 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1178 gdk_pixbuf_loader_close (loader, &error);
1181 g_error_free (error);
1182 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1184 g_object_ref (pixbuf);
1185 g_object_unref (loader);
1190 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1191 GdkPixbuf *new_pixbuf;
1193 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1194 gdk_pixbuf_get_width (pixbuf);
1195 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1196 g_object_unref (pixbuf);
1197 pixbuf = new_pixbuf;
1201 *stream_size = size;
1207 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1209 ModestMsgEditWindowPrivate *priv;
1212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1214 g_object_ref (self);
1215 for (iter = tny_list_create_iterator (attachments);
1216 !tny_iterator_is_done (iter);
1217 tny_iterator_next (iter)) {
1218 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1219 const gchar *cid = tny_mime_part_get_content_id (part);
1220 const gchar *mime_type = tny_mime_part_get_content_type (part);
1221 if ((cid != NULL)&&(mime_type != NULL)) {
1222 guint64 stream_size;
1223 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1224 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1227 g_object_unref (stream);
1229 if (pixbuf != NULL) {
1230 priv->images_count ++;
1231 priv->images_size += stream_size;
1232 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1233 g_object_unref (pixbuf);
1236 g_object_unref (part);
1238 g_object_unref (iter);
1239 g_object_unref (self);
1243 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1245 TnyMimePart *parent = NULL;
1246 const gchar *content_type = NULL;
1247 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1249 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1251 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1252 parent = g_object_ref (msg);
1253 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1254 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1257 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1258 iter = tny_list_create_iterator (parts);
1259 while (!tny_iterator_is_done (iter)) {
1261 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1262 content_type = tny_mime_part_get_content_type (part);
1263 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1267 g_object_unref (part);
1269 tny_iterator_next (iter);
1271 g_object_unref (iter);
1272 g_object_unref (parts);
1275 if (parent != NULL) {
1276 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1279 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1280 iter = tny_list_create_iterator (parts);
1281 while (!tny_iterator_is_done (iter)) {
1283 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1284 content_type = tny_mime_part_get_content_type (part);
1285 if (content_type && g_str_has_prefix (content_type, "image/")) {
1286 tny_list_prepend (priv->images, (GObject *) part);
1288 g_object_unref (part);
1289 tny_iterator_next (iter);
1291 g_object_unref (iter);
1292 g_object_unref (parts);
1293 g_object_unref (parent);
1298 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1301 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1303 for (iter = tny_list_create_iterator (attachments) ;
1304 !tny_iterator_is_done (iter);
1305 tny_iterator_next (iter)) {
1306 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1307 const gchar *cid = tny_mime_part_get_content_id (part);
1309 char *invalid = NULL;
1310 gint int_cid = strtol (cid, &invalid, 10);
1311 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1312 priv->next_cid = int_cid + 1;
1315 g_object_unref (part);
1317 g_object_unref (iter);
1321 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1324 gchar *to, *cc, *bcc, *subject;
1326 ModestMsgEditWindowPrivate *priv;
1327 ModestWindowPrivate *parent_priv;
1329 TnyHeaderFlags priority_flags;
1330 TnyFolder *msg_folder;
1331 gboolean is_html = FALSE;
1332 gboolean field_view_set;
1334 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1335 g_return_if_fail (TNY_IS_MSG (msg));
1337 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1338 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1340 header = tny_msg_get_header (msg);
1341 to = tny_header_dup_to (header);
1342 cc = tny_header_dup_cc (header);
1343 bcc = tny_header_dup_bcc (header);
1344 subject = tny_header_dup_subject (header);
1346 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1347 priority_flags = tny_header_get_priority (header);
1350 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1352 field_view_set = TRUE;
1354 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1355 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1356 gtk_widget_show (priv->cc_caption);
1357 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1358 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1359 gtk_widget_hide (priv->cc_caption);
1360 field_view_set = FALSE;
1362 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1364 field_view_set = TRUE;
1366 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1367 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1368 gtk_widget_show (priv->bcc_caption);
1369 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1370 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1371 gtk_widget_hide (priv->bcc_caption);
1372 field_view_set = FALSE;
1374 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1378 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1379 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1382 update_window_title (self);
1384 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1385 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1387 if ((body == NULL)||(body[0] == '\0')) {
1389 body = modest_text_utils_convert_to_html ("");
1392 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1393 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1396 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1399 /* Add attachments to the view */
1400 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1401 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1402 if (tny_list_get_length (priv->attachments) == 0) {
1403 gtk_widget_hide (priv->attachments_caption);
1405 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1406 gtk_widget_show_all (priv->attachments_caption);
1408 get_related_images (self, msg);
1409 update_next_cid (self, priv->attachments);
1410 update_next_cid (self, priv->images);
1411 replace_with_images (self, priv->images);
1413 if (preserve_is_rich && !is_html) {
1414 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1415 /* Get the default format required from configuration */
1416 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1417 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1420 /* Set the default focus depending on having already a To: field or not */
1421 if ((!to)||(*to == '\0')) {
1422 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1424 gtk_widget_grab_focus (priv->msg_body);
1427 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1429 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1430 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1432 modest_msg_edit_window_set_modified (self, FALSE);
1434 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1435 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1436 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1437 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1439 if (priv->msg_uid) {
1440 g_free (priv->msg_uid);
1441 priv->msg_uid = NULL;
1444 /* we should set a reference to the incoming message if it is a draft */
1445 msg_folder = tny_msg_get_folder (msg);
1447 if (modest_tny_folder_is_local_folder (msg_folder)) {
1448 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1449 if (type == TNY_FOLDER_TYPE_INVALID)
1450 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1452 if (type == TNY_FOLDER_TYPE_DRAFTS)
1453 priv->draft_msg = g_object_ref(msg);
1454 if (type == TNY_FOLDER_TYPE_OUTBOX)
1455 priv->outbox_msg = g_object_ref(msg);
1456 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1458 g_object_unref (msg_folder);
1469 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1471 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1472 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1473 GtkWidget *placeholder;
1474 GtkWidget *tool_item;
1479 GtkWidget *sizes_menu;
1480 GtkWidget *fonts_menu;
1486 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1487 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1488 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1489 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1491 /* Font color placeholder */
1492 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1493 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1496 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1497 priv->font_color_button = hildon_color_button_new ();
1498 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1499 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1500 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1501 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1502 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1503 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1504 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1505 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1507 G_CALLBACK (modest_msg_edit_window_color_button_change),
1510 /* Font size and face placeholder */
1511 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1512 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1514 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1515 priv->size_tool_button_label = gtk_label_new (NULL);
1516 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1517 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1518 size_text, "</span>", NULL);
1519 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1520 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1522 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1523 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1524 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1525 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1526 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1527 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1528 gtk_widget_set_sensitive (arrow, FALSE);
1529 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1530 sizes_menu = gtk_menu_new ();
1531 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1532 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1535 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1536 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1538 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1542 if (wp_font_size[size_index] == 12)
1543 priv->current_size_index = size_index;
1547 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1548 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1549 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1550 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1551 priv->font_size_toolitem = tool_item;
1554 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1555 priv->font_tool_button_label = gtk_label_new (NULL);
1556 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1557 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1558 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1560 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1561 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1562 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1563 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1564 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1565 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1566 gtk_widget_set_sensitive (arrow, FALSE);
1567 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1568 fonts_menu = gtk_menu_new ();
1569 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1570 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1573 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1575 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1576 0, wp_get_font_name (font_index),
1579 if (font_index == DEFAULT_FONT)
1580 priv->current_face_index = font_index;
1582 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1583 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1584 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1585 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1586 priv->font_face_toolitem = tool_item;
1588 /* Set expand and homogeneous for remaining items */
1589 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1590 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1591 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1592 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1593 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1594 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1596 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1597 will not show the tool items added to the placeholders) */
1598 gtk_widget_show_all (parent_priv->toolbar);
1600 /* Set the no show all *after* showing all items. We do not
1601 want the toolbar to be shown with a show all because it
1602 could go agains the gconf setting regarding showing or not
1603 the toolbar of the editor window */
1604 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1610 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1613 ModestWindowPrivate *parent_priv;
1614 ModestMsgEditWindowPrivate *priv;
1615 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1616 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1617 ModestWindowMgr *mgr = NULL;
1619 g_return_val_if_fail (msg, NULL);
1620 g_return_val_if_fail (account_name, NULL);
1622 mgr = modest_runtime_get_window_mgr ();
1624 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1626 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1627 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1629 /* Menubar. Update the state of some toggles */
1630 priv->from_field_protos = get_transports ();
1631 priv->original_mailbox = NULL;
1632 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1633 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1634 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1635 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1636 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1637 priv->original_mailbox = g_strdup (mailbox);
1638 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1639 /* We set the first mailbox as the active mailbox */
1640 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1641 if (priv->original_mailbox != NULL)
1642 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1643 (gpointer) priv->original_mailbox);
1645 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1646 (gpointer) account_name);
1648 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1650 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1651 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1652 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1654 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1655 hildon_touch_selector_get_current_text
1656 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1657 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1658 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1661 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1663 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1665 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1666 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1668 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1670 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1671 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1672 /* Add common dimming rules */
1673 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1674 modest_msg_edit_window_toolbar_dimming_entries,
1675 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1676 MODEST_WINDOW (obj));
1677 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1678 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1679 MODEST_WINDOW (obj));
1680 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1681 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1682 MODEST_WINDOW (obj));
1683 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1684 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1685 MODEST_WINDOW (obj));
1686 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1687 G_CALLBACK (modest_ui_dimming_rules_on_send),
1688 MODEST_WINDOW (obj));
1689 /* Insert dimming rules group for this window */
1690 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1691 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1693 /* Setup app menu */
1694 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1696 /* Checks the dimming rules */
1697 g_object_unref (toolbar_rules_group);
1698 g_object_unref (clipboard_rules_group);
1699 gtk_widget_hide (priv->priority_icon);
1700 gtk_widget_queue_resize (priv->subject_box);
1701 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1703 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1705 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1706 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1707 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1708 priv->update_caption_visibility = TRUE;
1710 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1712 /* Track account-removed signal, this window should be closed
1713 in the case we're creating a mail associated to the account
1715 priv->account_removed_handler_id =
1716 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1718 G_CALLBACK(on_account_removed),
1721 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1723 return (ModestWindow*) obj;
1727 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1729 GString **string_buffer = (GString **) user_data;
1731 *string_buffer = g_string_append (*string_buffer, buffer);
1737 * @result: A new string which should be freed with g_free().
1740 get_formatted_data (ModestMsgEditWindow *edit_window)
1742 ModestMsgEditWindowPrivate *priv;
1743 GString *string_buffer = g_string_new ("");
1745 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1747 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1749 modest_text_utils_hyperlinkify (string_buffer);
1751 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1753 return g_string_free (string_buffer, FALSE);
1758 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1761 const gchar *account_name;
1762 ModestMsgEditWindowPrivate *priv;
1763 TnyIterator *att_iter;
1764 const gchar *picker_active_id;
1766 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1770 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1771 g_return_val_if_fail (picker_active_id, NULL);
1772 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1774 /* don't free these (except from) */
1775 data = g_slice_new0 (MsgData);
1776 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1777 data->account_name = g_strdup (account_name);
1778 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1779 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1780 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1781 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1782 data->references = g_strdup (priv->references);
1783 data->in_reply_to = g_strdup (priv->in_reply_to);
1784 if (priv->draft_msg) {
1785 data->draft_msg = g_object_ref (priv->draft_msg);
1786 } else if (priv->outbox_msg) {
1787 data->draft_msg = g_object_ref (priv->outbox_msg);
1789 data->draft_msg = NULL;
1792 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1794 gtk_text_buffer_get_bounds (buf, &b, &e);
1795 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1797 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1798 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1800 data->html_body = NULL;
1802 /* deep-copy the data */
1803 att_iter = tny_list_create_iterator (priv->attachments);
1804 data->attachments = NULL;
1805 while (!tny_iterator_is_done (att_iter)) {
1806 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1807 if (!(TNY_IS_MIME_PART(part))) {
1808 g_warning ("strange data in attachment list");
1809 g_object_unref (part);
1810 tny_iterator_next (att_iter);
1813 data->attachments = g_list_append (data->attachments,
1815 tny_iterator_next (att_iter);
1817 g_object_unref (att_iter);
1819 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1820 att_iter = tny_list_create_iterator (priv->images);
1821 data->images = NULL;
1822 while (!tny_iterator_is_done (att_iter)) {
1823 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1825 if (!(TNY_IS_MIME_PART(part))) {
1826 g_warning ("strange data in attachment list");
1827 g_object_unref (part);
1828 tny_iterator_next (att_iter);
1831 cid = tny_mime_part_get_content_id (part);
1833 gchar *image_tag_id;
1834 GtkTextTag *image_tag;
1836 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1837 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1838 g_free (image_tag_id);
1840 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1842 ((gtk_text_iter_has_tag (&iter, image_tag))||
1843 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1844 data->images = g_list_append (data->images,
1845 g_object_ref (part));
1847 g_object_unref (part);
1848 tny_iterator_next (att_iter);
1850 g_object_unref (att_iter);
1852 data->priority_flags = priv->priority_flags;
1859 unref_gobject (GObject *obj, gpointer data)
1861 if (!G_IS_OBJECT(obj))
1863 g_object_unref (obj);
1867 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1870 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1878 g_free (data->from);
1879 g_free (data->subject);
1880 g_free (data->plain_body);
1881 g_free (data->html_body);
1882 g_free (data->account_name);
1883 g_free (data->references);
1884 g_free (data->in_reply_to);
1886 if (data->draft_msg != NULL) {
1887 g_object_unref (data->draft_msg);
1888 data->draft_msg = NULL;
1891 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1892 g_list_free (data->attachments);
1893 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1894 g_list_free (data->images);
1896 g_slice_free (MsgData, data);
1900 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1902 guint64 *parts_size)
1904 ModestMsgEditWindowPrivate *priv;
1906 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1908 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1910 /* TODO: add images */
1911 *parts_size += priv->images_size;
1912 *parts_count += priv->images_count;
1917 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1920 ModestMsgEditWindowPrivate *priv = NULL;
1921 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1923 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1925 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1927 return MODEST_MSG_EDIT_FORMAT_HTML;
1929 return MODEST_MSG_EDIT_FORMAT_TEXT;
1933 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1934 ModestMsgEditFormat format)
1936 ModestMsgEditWindowPrivate *priv;
1937 ModestWindowPrivate *parent_priv;
1939 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1941 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1944 case MODEST_MSG_EDIT_FORMAT_HTML:
1945 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1946 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1948 case MODEST_MSG_EDIT_FORMAT_TEXT:
1949 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1950 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1953 g_return_if_reached ();
1957 ModestMsgEditFormatState *
1958 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1960 ModestMsgEditFormatState *format_state = NULL;
1961 ModestMsgEditWindowPrivate *priv;
1962 WPTextBufferFormat *buffer_format;
1964 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1966 buffer_format = g_new0 (WPTextBufferFormat, 1);
1967 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1969 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1971 format_state = g_new0 (ModestMsgEditFormatState, 1);
1972 format_state->bold = buffer_format->bold&0x1;
1973 format_state->italics = buffer_format->italic&0x1;
1974 format_state->bullet = buffer_format->bullet&0x1;
1975 format_state->color = buffer_format->color;
1976 format_state->font_size = buffer_format->font_size;
1977 format_state->font_family = wp_get_font_name (buffer_format->font);
1978 format_state->justification = buffer_format->justification;
1979 g_free (buffer_format);
1981 return format_state;
1986 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1987 const ModestMsgEditFormatState *format_state)
1989 ModestMsgEditWindowPrivate *priv;
1990 WPTextBufferFormat *buffer_format;
1991 WPTextBufferFormat *current_format;
1993 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1994 g_return_if_fail (format_state != NULL);
1996 buffer_format = g_new0 (WPTextBufferFormat, 1);
1997 current_format = g_new0 (WPTextBufferFormat, 1);
1999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2000 gtk_widget_grab_focus (priv->msg_body);
2001 buffer_format->bold = (format_state->bold != FALSE);
2002 buffer_format->italic = (format_state->italics != FALSE);
2003 buffer_format->color = format_state->color;
2004 buffer_format->font_size = format_state->font_size;
2005 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2006 buffer_format->justification = format_state->justification;
2007 buffer_format->bullet = format_state->bullet;
2009 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2011 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2012 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2013 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2014 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2015 buffer_format->cs.font = (buffer_format->font != current_format->font);
2016 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2017 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2019 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2020 if (buffer_format->cs.bold) {
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2022 GINT_TO_POINTER (buffer_format->bold&0x1));
2024 if (buffer_format->cs.italic) {
2025 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2026 GINT_TO_POINTER (buffer_format->italic&0x1));
2028 if (buffer_format->cs.color) {
2029 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2030 GINT_TO_POINTER (&(buffer_format->color)));
2032 if (buffer_format->cs.font_size) {
2033 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2034 GINT_TO_POINTER (buffer_format->font_size));
2036 if (buffer_format->cs.justification) {
2037 switch (buffer_format->justification) {
2038 case GTK_JUSTIFY_LEFT:
2039 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2040 GINT_TO_POINTER(TRUE));
2042 case GTK_JUSTIFY_CENTER:
2043 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2044 GINT_TO_POINTER(TRUE));
2046 case GTK_JUSTIFY_RIGHT:
2047 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2048 GINT_TO_POINTER(TRUE));
2055 if (buffer_format->cs.font) {
2056 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2057 GINT_TO_POINTER (buffer_format->font));
2059 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2060 if (buffer_format->cs.bullet) {
2061 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2062 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2064 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2066 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2068 g_free (buffer_format);
2069 g_free (current_format);
2071 /* Check dimming rules */
2072 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2073 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2077 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2079 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2081 ModestWindowPrivate *parent_priv;
2082 ModestMsgEditWindowPrivate *priv;
2084 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2085 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2087 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2088 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2089 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2090 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2092 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2093 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2094 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2097 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2099 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2100 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2102 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2103 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2105 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2106 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2109 switch (buffer_format->justification)
2111 case GTK_JUSTIFY_LEFT:
2112 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2114 case GTK_JUSTIFY_CENTER:
2115 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2117 case GTK_JUSTIFY_RIGHT:
2118 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2125 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2127 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2128 G_CALLBACK (modest_msg_edit_window_color_button_change),
2130 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2131 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2132 G_CALLBACK (modest_msg_edit_window_color_button_change),
2135 if (priv->current_size_index != buffer_format->font_size) {
2139 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2140 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2144 priv->current_size_index = buffer_format->font_size;
2146 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2147 markup = g_strconcat ("<span font_family='Sans'>",
2148 size_text, "</span>", NULL);
2150 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2154 gtk_tree_path_free (path);
2157 if (priv->current_face_index != buffer_format->font) {
2161 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2162 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2166 priv->current_face_index = buffer_format->font;
2167 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2168 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2169 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2176 g_free (buffer_format);
2180 #ifdef MODEST_HILDON_VERSION_0
2182 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2185 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2186 ModestMsgEditWindowPrivate *priv;
2187 GtkWidget *dialog = NULL;
2189 GdkColor *new_color = NULL;
2191 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2192 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2194 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2195 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2196 g_free (buffer_format);
2198 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2199 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2200 if (new_color != NULL) {
2201 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2202 (gpointer) new_color);
2205 gtk_widget_destroy (dialog);
2210 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2213 ModestMsgEditWindowPrivate *priv;
2214 GtkWidget *dialog = NULL;
2216 GdkColor *old_color = NULL;
2217 const GdkColor *new_color = NULL;
2219 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2220 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2222 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2223 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2225 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2226 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2227 if (new_color != NULL)
2228 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2230 gtk_widget_destroy (dialog);
2236 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2239 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2240 ModestMsgEditWindowPrivate *priv;
2241 GtkWidget *dialog = NULL;
2243 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2244 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2246 dialog = hildon_color_chooser_new ();
2247 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2248 g_free (buffer_format);
2250 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2252 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2253 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2256 gtk_widget_destroy (dialog);
2261 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2264 ModestMsgEditWindowPrivate *priv;
2265 GtkWidget *dialog = NULL;
2266 GdkColor *old_color = NULL;
2268 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2269 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2271 dialog = hildon_color_chooser_new ();
2272 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2274 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2276 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2277 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2279 gtk_widget_destroy (dialog);
2282 #endif /*!MODEST_HILDON_VERSION_0*/
2287 create_stream_for_uri (const gchar* uri)
2292 TnyStream *result = NULL;
2294 GnomeVFSHandle *handle = NULL;
2295 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2296 if (test == GNOME_VFS_OK) {
2297 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2298 /* Streams over OBEX (Bluetooth) are not seekable but
2299 * we expect them to be (we might need to read them
2300 * several times). So if this is a Bluetooth URI just
2301 * read the whole file into memory (this is not a fast
2302 * protocol so we can assume that these files are not
2303 * going to be very big) */
2304 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2305 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2306 TnyStream *memstream = tny_camel_mem_stream_new ();
2307 tny_stream_write_to_stream (vfssstream, memstream);
2308 g_object_unref (vfssstream);
2311 result = vfssstream;
2319 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2322 ModestMsgEditWindowPrivate *priv;
2323 GtkWidget *dialog = NULL;
2325 GSList *uris = NULL;
2326 GSList *uri_node = NULL;
2328 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2330 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2331 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2332 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2334 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2336 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2337 GTK_WINDOW (dialog), GTK_WINDOW (window));
2339 response = gtk_dialog_run (GTK_DIALOG (dialog));
2341 case GTK_RESPONSE_OK:
2343 gchar *current_folder;
2344 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2345 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2346 if (current_folder && current_folder != '\0') {
2348 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2349 current_folder, &err);
2351 g_debug ("Error storing latest used folder: %s", err->message);
2355 g_free (current_folder);
2361 gtk_widget_destroy (dialog);
2363 g_object_ref (window);
2364 /* The operation could take some time so allow the dialog to be closed */
2365 while (gtk_events_pending ())
2366 gtk_main_iteration ();
2368 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2370 GnomeVFSHandle *handle = NULL;
2371 GnomeVFSResult result;
2372 GtkTextIter position;
2373 GtkTextMark *insert_mark;
2375 uri = (const gchar *) uri_node->data;
2376 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2377 if (result == GNOME_VFS_OK) {
2379 GnomeVFSFileInfo *info;
2380 gchar *filename, *basename, *escaped_filename;
2381 TnyMimePart *mime_part;
2383 const gchar *mime_type = NULL;
2384 GnomeVFSURI *vfs_uri;
2385 guint64 stream_size;
2387 gnome_vfs_close (handle);
2388 vfs_uri = gnome_vfs_uri_new (uri);
2390 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2391 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2392 g_free (escaped_filename);
2393 gnome_vfs_uri_unref (vfs_uri);
2394 info = gnome_vfs_file_info_new ();
2396 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2397 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2399 mime_type = gnome_vfs_file_info_get_mime_type (info);
2401 mime_part = tny_platform_factory_new_mime_part
2402 (modest_runtime_get_platform_factory ());
2404 TnyStream *stream = create_stream_for_uri (uri);
2406 if (stream == NULL) {
2408 modest_platform_information_banner (NULL, NULL,
2409 _FM("sfil_ib_opening_not_allowed"));
2411 g_object_unref (mime_part);
2412 gnome_vfs_file_info_unref (info);
2416 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2418 content_id = g_strdup_printf ("%d", priv->next_cid);
2419 tny_mime_part_set_content_id (mime_part, content_id);
2420 g_free (content_id);
2423 basename = g_path_get_basename (filename);
2424 tny_mime_part_set_filename (mime_part, basename);
2427 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2429 if (pixbuf != NULL) {
2430 priv->images_size += stream_size;
2431 priv->images_count ++;
2432 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2433 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2434 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2435 tny_mime_part_get_content_id (mime_part), pixbuf);
2436 g_object_unref (pixbuf);
2438 tny_list_prepend (priv->images, (GObject *) mime_part);
2439 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2441 modest_platform_information_banner (NULL, NULL,
2442 _("mail_ib_file_operation_failed"));
2446 g_object_unref (mime_part);
2447 gnome_vfs_file_info_unref (info);
2451 g_object_unref (window);
2455 on_attach_file_response (GtkDialog *dialog,
2459 GSList *uris = NULL;
2461 GnomeVFSFileSize total_size, allowed_size;
2462 ModestMsgEditWindow *window;
2463 ModestMsgEditWindowPrivate *priv;
2468 case GTK_RESPONSE_OK:
2470 gchar *current_folder;
2472 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2473 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2474 if (current_folder && current_folder != '\0') {
2476 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2477 current_folder, &err);
2479 g_debug ("Error storing latest used folder: %s", err->message);
2483 g_free (current_folder);
2490 window = MODEST_MSG_EDIT_WINDOW (user_data);
2491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2493 /* allowed size is the maximum size - what's already there */
2494 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2495 &att_num, &att_size);
2496 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2499 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2501 const gchar *uri = (const gchar *) uri_node->data;
2504 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2506 if (total_size > allowed_size) {
2507 g_debug ("%s: total size: %u",
2508 __FUNCTION__, (unsigned int)total_size);
2511 allowed_size -= total_size;
2513 g_slist_foreach (uris, (GFunc) g_free, NULL);
2514 g_slist_free (uris);
2516 gtk_widget_destroy (GTK_WIDGET (dialog));
2520 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2522 GtkWidget *dialog = NULL;
2523 ModestMsgEditWindowPrivate *priv;
2526 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2530 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2533 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2534 GTK_FILE_CHOOSER_ACTION_OPEN);
2535 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2536 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2537 if (conf_folder && conf_folder[0] != '\0') {
2538 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2541 /* Set the default folder to images folder */
2542 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2543 ".documents", NULL);
2544 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2545 g_free (docs_folder);
2547 g_free (conf_folder);
2548 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2549 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2550 GTK_WINDOW (dialog), GTK_WINDOW (window));
2552 /* Connect to response & show */
2553 g_signal_connect (dialog, "response",
2554 G_CALLBACK (on_attach_file_response), window);
2555 gtk_widget_show (dialog);
2560 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2562 GnomeVFSFileSize allowed_size)
2565 GnomeVFSHandle *handle = NULL;
2566 ModestMsgEditWindowPrivate *priv;
2567 GnomeVFSResult result;
2568 GnomeVFSFileSize size = 0;
2569 g_return_val_if_fail (window, 0);
2570 g_return_val_if_fail (uri, 0);
2572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2574 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2575 if (result == GNOME_VFS_OK) {
2576 TnyMimePart *mime_part;
2578 const gchar *mime_type = NULL;
2580 gchar *escaped_filename;
2583 GnomeVFSFileInfo *info;
2584 GnomeVFSURI *vfs_uri;
2586 gnome_vfs_close (handle);
2587 vfs_uri = gnome_vfs_uri_new (uri);
2590 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2591 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2592 g_free (escaped_filename);
2593 gnome_vfs_uri_unref (vfs_uri);
2595 info = gnome_vfs_file_info_new ();
2597 if (gnome_vfs_get_file_info (uri,
2599 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2601 mime_type = gnome_vfs_file_info_get_mime_type (info);
2602 mime_part = tny_platform_factory_new_mime_part
2603 (modest_runtime_get_platform_factory ());
2605 /* try to get the attachment's size; this may fail for weird
2606 * file systems, like obex, upnp... */
2607 if (allowed_size != 0 &&
2608 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2610 if (size > allowed_size) {
2611 modest_platform_information_banner (NULL, NULL,
2612 _("mail_ib_error_attachment_size"));
2617 g_debug ("%s: could not get attachment size", __FUNCTION__);
2619 stream = create_stream_for_uri (uri);
2621 if (stream == NULL) {
2623 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2625 g_object_unref (mime_part);
2627 gnome_vfs_file_info_unref (info);
2631 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2632 g_object_unref (stream);
2634 content_id = g_strdup_printf ("%d", priv->next_cid);
2635 tny_mime_part_set_content_id (mime_part, content_id);
2636 g_free (content_id);
2639 basename = g_path_get_basename (filename);
2640 tny_mime_part_set_filename (mime_part, basename);
2643 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2644 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2646 info->size == 0, info->size);
2647 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2648 gtk_widget_show_all (priv->attachments_caption);
2649 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2651 g_object_unref (mime_part);
2652 gnome_vfs_file_info_unref (info);
2659 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2662 ModestMsgEditWindowPrivate *priv;
2665 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2668 if (att_list == NULL) {
2669 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2670 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2671 g_object_unref (att_list);
2675 g_object_ref (att_list);
2678 if (tny_list_get_length (att_list) == 0) {
2679 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2681 gboolean dialog_response;
2682 gchar *message = NULL;
2683 gchar *filename = NULL;
2685 if (tny_list_get_length (att_list) == 1) {
2687 iter = tny_list_create_iterator (att_list);
2688 part = (TnyMimePart *) tny_iterator_get_current (iter);
2689 g_object_unref (iter);
2690 if (TNY_IS_MSG (part)) {
2691 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2693 filename = tny_header_dup_subject (header);
2694 g_object_unref (header);
2696 if (filename == NULL) {
2697 filename = g_strdup (_("mail_va_no_subject"));
2700 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2702 g_object_unref (part);
2704 filename = g_strdup ("");
2706 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2707 "emev_nc_delete_attachments",
2708 tny_list_get_length (att_list)), filename);
2711 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2715 if (dialog_response != GTK_RESPONSE_OK) {
2716 g_object_unref (att_list);
2720 for (iter = tny_list_create_iterator (att_list);
2721 !tny_iterator_is_done (iter);
2722 tny_iterator_next (iter)) {
2723 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2724 const gchar *att_id;
2725 tny_list_remove (priv->attachments, (GObject *) mime_part);
2727 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2729 if (tny_list_get_length (priv->attachments) == 0)
2730 gtk_widget_hide (priv->attachments_caption);
2731 att_id = tny_mime_part_get_content_id (mime_part);
2733 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2735 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2736 g_object_unref (mime_part);
2738 g_object_unref (iter);
2741 g_object_unref (att_list);
2743 /* if the last attachment has been removed, focus the Subject: field */
2744 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2745 gtk_widget_grab_focus (priv->subject_field);
2749 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2752 ModestMsgEditWindowPrivate *priv;
2753 GdkColor *new_color;
2754 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2756 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2757 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2760 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2762 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2764 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2766 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2771 font_size_clicked (GtkToolButton *button,
2772 ModestMsgEditWindow *window)
2774 ModestMsgEditWindowPrivate *priv;
2775 GtkWidget *selector, *dialog;
2777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2779 selector = hildon_touch_selector_new ();
2780 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2781 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2783 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2784 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2785 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2787 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2791 WPTextBufferFormat format;
2793 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2795 memset (&format, 0, sizeof (format));
2796 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2798 format.cs.font_size = TRUE;
2799 format.cs.text_position = TRUE;
2800 format.cs.font = TRUE;
2801 format.font_size = new_index;
2802 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2804 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2805 GINT_TO_POINTER (new_index)))
2806 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2808 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2809 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2810 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2811 size_text, "</span>", NULL);
2813 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2817 gtk_widget_destroy (dialog);
2819 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2824 font_face_clicked (GtkToolButton *button,
2825 ModestMsgEditWindow *window)
2827 ModestMsgEditWindowPrivate *priv;
2828 GtkWidget *selector, *dialog;
2829 GtkCellRenderer *renderer;
2831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2833 selector = hildon_touch_selector_new ();
2834 renderer = gtk_cell_renderer_text_new ();
2835 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2836 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2837 renderer, "family", 0, "text", 0, NULL);
2838 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2840 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2841 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2842 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2844 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2845 gint new_font_index;
2849 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2850 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2851 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2855 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2857 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2858 GINT_TO_POINTER(new_font_index)))
2859 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2861 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2862 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2864 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2868 gtk_tree_path_free (path);
2871 gtk_widget_destroy (dialog);
2873 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2878 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2881 ModestMsgEditWindowPrivate *priv = NULL;
2882 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2884 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2885 if (!priv->update_caption_visibility)
2888 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2890 gtk_widget_show (priv->cc_caption);
2892 gtk_widget_hide (priv->cc_caption);
2894 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2898 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2901 ModestMsgEditWindowPrivate *priv = NULL;
2902 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2904 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2905 if (!priv->update_caption_visibility)
2908 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2910 gtk_widget_show (priv->bcc_caption);
2912 gtk_widget_hide (priv->bcc_caption);
2914 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2918 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2919 ModestRecptEditor *editor)
2921 ModestMsgEditWindowPrivate *priv;
2923 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2924 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2926 /* we check for low-mem; in that case, show a warning, and don't allow
2927 * for the addressbook
2929 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2934 if (editor == NULL) {
2935 GtkWidget *view_focus, *parent;
2936 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2938 /* This code should be kept in sync with ModestRecptEditor. The
2939 textview inside the recpt editor is the one that really gets the
2940 focus. As it's inside a scrolled window, and this one inside the
2941 hbox recpt editor inherits from, we'll need to go up in the
2942 hierarchy to know if the text view is part of the recpt editor
2943 or if it's a different text entry */
2944 parent = gtk_widget_get_parent (view_focus);
2945 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2946 editor = MODEST_RECPT_EDITOR (parent);
2949 editor = MODEST_RECPT_EDITOR (priv->to_field);
2952 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2956 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2958 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2960 modest_msg_edit_window_open_addressbook (window, NULL);
2964 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2965 gboolean show_toolbar)
2967 ModestWindowPrivate *parent_priv;
2968 ModestMsgEditWindowPrivate *priv;
2970 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2971 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2972 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2974 /* We can not just use the code of
2975 modest_msg_edit_window_setup_toolbar because it has a
2976 mixture of both initialization and creation code. */
2978 gint current_format;
2979 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2980 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2981 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2982 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2984 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2987 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2992 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2993 TnyHeaderFlags priority_flags)
2995 ModestMsgEditWindowPrivate *priv;
2996 ModestWindowPrivate *parent_priv;
2998 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3001 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3003 if (priv->priority_flags != priority_flags) {
3004 GtkAction *priority_action = NULL;
3006 priv->priority_flags = priority_flags;
3008 switch (priority_flags) {
3009 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3010 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3011 MODEST_HEADER_ICON_HIGH,
3012 HILDON_ICON_SIZE_SMALL);
3013 gtk_widget_show (priv->priority_icon);
3014 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3015 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3017 case TNY_HEADER_FLAG_LOW_PRIORITY:
3018 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3019 MODEST_HEADER_ICON_LOW,
3020 HILDON_ICON_SIZE_SMALL);
3021 gtk_widget_show (priv->priority_icon);
3022 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3023 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3026 gtk_widget_hide (priv->priority_icon);
3027 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3028 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3031 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3032 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3034 gtk_widget_queue_resize (priv->subject_box);
3038 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3041 ModestMsgEditWindowPrivate *priv;
3042 ModestWindowPrivate *parent_priv;
3043 gint current_format;
3045 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3047 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3048 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3050 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3051 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3053 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3055 if (parent_priv->toolbar) {
3056 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3057 gtk_widget_hide (parent_priv->toolbar);
3059 gtk_widget_show (parent_priv->toolbar);
3063 if (current_format != file_format) {
3064 switch (file_format) {
3065 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3066 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3067 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3069 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3073 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3074 response = gtk_dialog_run (GTK_DIALOG (dialog));
3075 gtk_widget_destroy (dialog);
3076 if (response == GTK_RESPONSE_OK) {
3077 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3078 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3080 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3081 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3086 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3087 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3088 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3093 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3096 ModestMsgEditWindowPrivate *priv;
3097 WPTextBufferFormat oldfmt, fmt;
3098 gint old_position = 0;
3102 GdkColor *color = NULL;
3103 gboolean bold, bold_set, italic, italic_set;
3104 gboolean underline, underline_set;
3105 gboolean strikethrough, strikethrough_set;
3106 gboolean position_set;
3107 gboolean font_size_set, font_set, color_set;
3110 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3111 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3113 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3114 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3115 GTK_WINDOW(dialog), GTK_WINDOW (window));
3117 /* First we get the currently selected font information */
3118 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3120 switch (oldfmt.text_position) {
3121 case TEXT_POSITION_NORMAL:
3124 case TEXT_POSITION_SUPERSCRIPT:
3132 g_object_set (G_OBJECT (dialog),
3133 "bold", oldfmt.bold != FALSE,
3134 "bold-set", !oldfmt.cs.bold,
3135 "underline", oldfmt.underline != FALSE,
3136 "underline-set", !oldfmt.cs.underline,
3137 "italic", oldfmt.italic != FALSE,
3138 "italic-set", !oldfmt.cs.italic,
3139 "strikethrough", oldfmt.strikethrough != FALSE,
3140 "strikethrough-set", !oldfmt.cs.strikethrough,
3141 "color", &oldfmt.color,
3142 "color-set", !oldfmt.cs.color,
3143 "size", wp_font_size[oldfmt.font_size],
3144 "size-set", !oldfmt.cs.font_size,
3145 "position", old_position,
3146 "position-set", !oldfmt.cs.text_position,
3147 "family", wp_get_font_name (oldfmt.font),
3148 "family-set", !oldfmt.cs.font,
3151 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3152 GTK_WINDOW (dialog), GTK_WINDOW (window));
3153 gtk_widget_show_all (dialog);
3154 priv->font_dialog = dialog;
3155 response = gtk_dialog_run (GTK_DIALOG (dialog));
3156 priv->font_dialog = NULL;
3157 if (response == GTK_RESPONSE_OK) {
3159 g_object_get( dialog,
3161 "bold-set", &bold_set,
3162 "underline", &underline,
3163 "underline-set", &underline_set,
3165 "italic-set", &italic_set,
3166 "strikethrough", &strikethrough,
3167 "strikethrough-set", &strikethrough_set,
3169 "color-set", &color_set,
3171 "size-set", &font_size_set,
3172 "family", &font_name,
3173 "family-set", &font_set,
3174 "position", &position,
3175 "position-set", &position_set,
3180 if (response == GTK_RESPONSE_OK) {
3181 memset(&fmt, 0, sizeof(fmt));
3187 fmt.italic = italic;
3188 fmt.cs.italic = TRUE;
3190 if (underline_set) {
3191 fmt.underline = underline;
3192 fmt.cs.underline = TRUE;
3194 if (strikethrough_set) {
3195 fmt.strikethrough = strikethrough;
3196 fmt.cs.strikethrough = TRUE;
3201 ? TEXT_POSITION_NORMAL
3202 : ( ( position == 1 )
3203 ? TEXT_POSITION_SUPERSCRIPT
3204 : TEXT_POSITION_SUBSCRIPT );
3205 fmt.cs.text_position = TRUE;
3206 fmt.font_size = oldfmt.font_size;
3210 fmt.cs.color = TRUE;
3213 fmt.font = wp_get_font_index(font_name,
3218 if (font_size_set) {
3219 fmt.cs.font_size = TRUE;
3220 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3222 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3223 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3225 gtk_widget_destroy (dialog);
3227 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3231 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3233 ModestMsgEditWindowPrivate *priv;
3235 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3236 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3240 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3241 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3245 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3247 ModestMsgEditWindowPrivate *priv;
3249 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3250 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3252 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3254 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3255 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3260 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 priv->can_undo = can_undo;
3268 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3270 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3272 priv->can_redo = can_redo;
3276 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3278 ModestMsgEditWindowPrivate *priv;
3279 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3280 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3282 return priv->can_undo;
3286 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3288 ModestMsgEditWindowPrivate *priv;
3289 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3290 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3292 return priv->can_redo;
3297 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3300 GtkTextIter match_start, match_end;
3302 if (image_id == NULL)
3305 gtk_text_buffer_get_start_iter (buffer, &iter);
3307 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3308 GSList *tags = gtk_text_iter_get_tags (&match_start);
3310 for (node = tags; node != NULL; node = g_slist_next (node)) {
3311 GtkTextTag *tag = (GtkTextTag *) node->data;
3312 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3313 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3314 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3316 offset = gtk_text_iter_get_offset (&match_start);
3317 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3318 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3322 gtk_text_iter_forward_char (&iter);
3327 message_is_empty (ModestMsgEditWindow *window)
3329 ModestMsgEditWindowPrivate *priv = NULL;
3331 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3332 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3334 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3335 * so we can ignore markup.
3337 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3340 count = gtk_text_buffer_get_char_count (buf);
3346 msg_body_focus (GtkWidget *focus,
3347 GdkEventFocus *event,
3351 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3352 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3353 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3358 recpt_field_changed (GtkTextBuffer *buffer,
3359 ModestMsgEditWindow *editor)
3361 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3362 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3366 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3368 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3369 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3373 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3376 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3377 GtkTextBuffer *buffer;
3379 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3380 gtk_text_buffer_set_modified (buffer, modified);
3381 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3382 gtk_text_buffer_set_modified (buffer, modified);
3383 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3384 gtk_text_buffer_set_modified (buffer, modified);
3385 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3389 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3391 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3392 const char *account_name;
3393 GtkTextBuffer *buffer;
3395 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3396 if (gtk_text_buffer_get_modified (buffer))
3398 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3399 if (gtk_text_buffer_get_modified (buffer))
3401 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3402 if (gtk_text_buffer_get_modified (buffer))
3404 if (gtk_text_buffer_get_modified (priv->text_buffer))
3407 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3408 if (priv->original_mailbox) {
3409 if (!account_name || strcmp (account_name, priv->original_mailbox))
3411 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3422 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3424 ModestMsgEditWindowPrivate *priv = NULL;
3426 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3427 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3429 /* check if there's no recipient added */
3430 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3431 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3432 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3433 /* no recipient contents, then select contacts */
3434 modest_msg_edit_window_open_addressbook (window, NULL);
3438 g_object_ref (window);
3439 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3440 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3441 g_object_unref (window);
3444 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3445 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3446 g_object_unref (window);
3449 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3450 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3451 g_object_unref (window);
3455 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3456 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3457 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3458 g_object_unref (window);
3465 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3466 ModestMsgEditWindow *window)
3468 modest_msg_edit_window_offer_attach_file (window);
3472 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3474 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3476 return priv->clipboard_text;
3480 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3482 ModestMsgEditWindow *window)
3484 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3485 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3488 /* It could happen that the window was already closed */
3489 if (!GTK_WIDGET_VISIBLE (window))
3492 g_object_ref (window);
3493 text = gtk_clipboard_wait_for_text (selection_clipboard);
3495 if (priv->clipboard_text != NULL) {
3496 g_free (priv->clipboard_text);
3498 priv->clipboard_text = text;
3500 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3502 g_object_unref (window);
3505 static gboolean clipboard_owner_change_idle (gpointer userdata)
3507 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3508 ModestMsgEditWindowPrivate *priv;
3510 gdk_threads_enter ();
3511 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3514 priv->clipboard_owner_idle = 0;
3515 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3516 gdk_threads_leave ();
3522 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3524 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3525 if (priv->clipboard_owner_idle == 0) {
3526 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3527 clipboard_owner_change_idle,
3528 g_object_ref (window),
3534 subject_field_move_cursor (GtkEntry *entry,
3535 GtkMovementStep step,
3540 /* It could happen that the window was already closed */
3541 if (!GTK_WIDGET_VISIBLE (window))
3544 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3548 update_window_title (ModestMsgEditWindow *window)
3550 ModestMsgEditWindowPrivate *priv = NULL;
3551 const gchar *subject;
3553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3554 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3555 if (subject == NULL || subject[0] == '\0')
3556 subject = _("mail_va_new_email");
3558 gtk_window_set_title (GTK_WINDOW (window), subject);
3564 body_insert_text (GtkTextBuffer *buffer,
3565 GtkTextIter *location,
3568 ModestMsgEditWindow *window)
3570 GtkTextIter end_iter;
3574 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3576 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3578 offset = gtk_text_iter_get_offset (&end_iter);
3579 utf8_len = g_utf8_strlen (text, len);
3581 if (offset + utf8_len > MAX_BODY_LENGTH) {
3582 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3583 if (offset < MAX_BODY_LENGTH)
3588 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3590 /* Prevent endless recursion */
3591 result = g_strndup (text, utf8_end - text);
3592 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3593 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3594 (gpointer) result, (gpointer) (utf8_end - text),
3596 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3600 if (offset + utf8_len > MAX_BODY_LENGTH) {
3601 if (priv->max_chars_banner == NULL) {
3602 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3603 _CS("ckdg_ib_maximum_characters_reached"));
3604 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3610 subject_field_changed (GtkEditable *editable,
3611 ModestMsgEditWindow *window)
3613 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3614 update_window_title (window);
3615 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3616 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3617 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3620 subject_field_insert_text (GtkEditable *editable,
3622 gint new_text_length,
3624 ModestMsgEditWindow *window)
3626 GString *result = g_string_new ("");
3628 gint result_len = 0;
3629 const gchar *entry_text = NULL;
3632 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3633 old_length = g_utf8_strlen (entry_text, -1);
3635 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3636 gunichar c = g_utf8_get_char_validated (current, 8);
3637 /* Invalid unichar, stop */
3643 result = g_string_append_unichar (result, c);
3647 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3648 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3651 /* Prevent endless recursion */
3652 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3653 g_signal_emit_by_name (editable, "insert-text",
3654 (gpointer) result->str, (gpointer) result->len,
3655 (gpointer) position, (gpointer) window);
3656 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3660 if (result_len + old_length > 1000) {
3661 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3662 _CS("ckdg_ib_maximum_characters_reached"));
3664 g_string_free (result, TRUE);
3668 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3671 ModestMsgEditWindowPrivate *priv = NULL;
3673 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3674 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3676 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3679 gtk_widget_show_all (priv->find_toolbar);
3680 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3682 gtk_widget_hide_all (priv->find_toolbar);
3683 gtk_widget_grab_focus (priv->msg_body);
3688 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3690 GtkTextIter *match_start,
3691 GtkTextIter *match_end)
3693 GtkTextIter end_iter;
3694 gchar *str_casefold;
3697 gchar *range_casefold;
3700 gboolean result = FALSE;
3707 gtk_text_iter_forward_to_end (&end_iter);
3709 str_casefold = g_utf8_casefold (str, -1);
3710 str_chars_n = strlen (str);
3712 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3713 range_casefold = g_utf8_casefold (range_text, -1);
3714 range_chars_n = strlen (range_casefold);
3716 if (range_chars_n < str_chars_n) {
3717 g_free (str_casefold);
3718 g_free (range_text);
3719 g_free (range_casefold);
3723 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3724 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3725 if (!g_utf8_collate (range_subtext, str_casefold)) {
3726 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3728 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3729 match_start, match_end, NULL)) {
3730 g_debug ("Matched string with collate, but not matched in model");
3732 g_free (found_text);
3734 g_free (range_subtext);
3738 g_free (str_casefold);
3739 g_free (range_text);
3740 g_free (range_casefold);
3747 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3748 ModestMsgEditWindow *window)
3750 gchar *current_search = NULL;
3751 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3753 GtkTextIter selection_start, selection_end;
3754 GtkTextIter match_start, match_end;
3755 gboolean continue_search = FALSE;
3757 if (message_is_empty (window)) {
3758 g_free (priv->last_search);
3759 priv->last_search = NULL;
3760 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3764 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3765 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3766 g_free (current_search);
3767 g_free (priv->last_search);
3768 priv->last_search = NULL;
3769 /* Information banner about empty search */
3770 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3774 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3775 continue_search = TRUE;
3777 g_free (priv->last_search);
3778 priv->last_search = g_strdup (current_search);
3781 if (continue_search) {
3782 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3783 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3784 &match_start, &match_end);
3786 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3788 GtkTextIter buffer_start;
3789 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3790 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3791 &match_start, &match_end);
3793 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3796 /* Mark as selected the string found in search */
3798 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3799 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3800 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3802 g_free (priv->last_search);
3803 priv->last_search = NULL;
3805 g_free (current_search);
3809 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3811 ModestMsgEditWindowPrivate *priv;
3813 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3818 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3821 ModestMsgEditWindowPrivate *priv;
3823 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3828 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3829 ModestMsgEditWindow *window)
3831 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3835 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3838 ModestMsgEditWindowPrivate *priv;
3839 TnyHeader *header = NULL;
3841 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3842 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3846 if (priv->draft_msg != NULL) {
3847 g_object_unref (priv->draft_msg);
3850 if (draft != NULL) {
3851 g_object_ref (draft);
3852 header = tny_msg_get_header (draft);
3853 if (priv->msg_uid) {
3854 g_free (priv->msg_uid);
3855 priv->msg_uid = NULL;
3857 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3860 priv->draft_msg = draft;
3864 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3865 GtkTextIter *start, GtkTextIter *end,
3868 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3869 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3872 if (tag == NULL) return;
3873 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3874 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3875 replace_with_images (window, priv->images);
3880 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3883 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3885 g_return_if_fail (TNY_IS_MIME_PART (part));
3886 tny_list_prepend (priv->attachments, (GObject *) part);
3887 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3888 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3889 gtk_widget_show_all (priv->attachments_caption);
3890 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3894 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3896 ModestMsgEditWindowPrivate *priv;
3898 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3899 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3901 return priv->msg_uid;
3905 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3906 ModestMsgEditWindowWidgetType widget_type)
3908 ModestMsgEditWindowPrivate *priv;
3910 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3911 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3913 switch (widget_type) {
3914 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3915 return priv->msg_body;
3917 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3918 return priv->to_field;
3920 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3921 return priv->cc_field;
3923 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3924 return priv->bcc_field;
3926 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3927 return priv->subject_field;
3929 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3930 return priv->attachments_view;
3938 remove_tags (WPTextBuffer *buffer)
3940 GtkTextIter start, end;
3942 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3943 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3945 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3949 on_account_removed (TnyAccountStore *account_store,
3950 TnyAccount *account,
3953 /* Do nothing if it's a store account, because we use the
3954 transport to send the messages */
3955 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3956 const gchar *parent_acc = NULL;
3957 const gchar *our_acc = NULL;
3959 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3960 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3961 /* Close this window if I'm showing a message of the removed account */
3962 if (strcmp (parent_acc, our_acc) == 0)
3963 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3967 static void update_signature (ModestMsgEditWindow *self,
3968 const gchar *old_account,
3969 const gchar *new_account)
3971 ModestMsgEditWindowPrivate *priv;
3972 gboolean has_old_signature, has_new_signature;
3974 GtkTextIter match_start, match_end;
3975 ModestAccountMgr *mgr;
3977 gchar *full_signature;
3979 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3981 gtk_text_buffer_begin_user_action (priv->text_buffer);
3983 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3984 mgr = modest_runtime_get_account_mgr ();
3988 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3989 if (has_old_signature) {
3990 full_signature = g_strconcat ("\n--\n", signature, NULL);
3991 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3992 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3994 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3995 &match_start, &match_end, NULL)) {
3998 g_free (full_signature);
4003 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4004 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4005 if (has_new_signature) {
4006 full_signature = g_strconcat ("\n--\n", signature, NULL);
4007 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4008 g_free (full_signature);
4011 gtk_text_buffer_end_user_action (priv->text_buffer);
4014 static void update_branding (ModestMsgEditWindow *self,
4015 const gchar *new_account)
4017 ModestMsgEditWindowPrivate *priv;
4018 ModestAccountMgr *mgr;
4019 const GdkPixbuf *new_icon = NULL;
4020 gchar *new_label = NULL;
4021 gboolean show = FALSE;
4023 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4025 mgr = modest_runtime_get_account_mgr ();
4027 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4029 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4030 gtk_widget_show (priv->brand_icon);
4033 gtk_widget_hide (priv->brand_icon);
4036 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4037 gtk_widget_show (priv->brand_label);
4041 gtk_widget_hide (priv->brand_label);
4045 gtk_widget_show (priv->brand_container);
4047 gtk_widget_hide (priv->brand_container);
4051 from_field_changed (HildonPickerButton *button,
4052 ModestMsgEditWindow *self)
4054 ModestMsgEditWindowPrivate *priv;
4055 gchar *old_account, *new_account;
4057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4059 old_account = priv->last_from_account;
4060 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4061 new_account = priv->last_from_account;
4063 update_signature (self, old_account, new_account);
4064 update_branding (self, new_account);
4068 typedef struct _MessageSettingsHelper {
4069 ModestMsgEditWindow *window;
4070 GSList *priority_group;
4071 GSList *format_group;
4072 GtkToggleButton *current_priority;
4073 GtkToggleButton *current_format;
4074 } MessageSettingsHelper;
4077 on_priority_toggle (GtkToggleButton *button,
4078 MessageSettingsHelper *helper)
4081 ModestMsgEditWindowPrivate *priv;
4083 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4084 if (gtk_toggle_button_get_active (button)) {
4086 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4087 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4088 if ((node_button != button) &&
4089 gtk_toggle_button_get_active (node_button)) {
4090 gtk_toggle_button_set_active (node_button, FALSE);
4093 helper->current_priority = button;
4095 gboolean found = FALSE;
4096 /* If no one is active, activate it again */
4097 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4098 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4099 if (gtk_toggle_button_get_active (node_button)) {
4105 gtk_toggle_button_set_active (button, TRUE);
4111 on_format_toggle (GtkToggleButton *button,
4112 MessageSettingsHelper *helper)
4115 ModestMsgEditWindowPrivate *priv;
4117 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4118 if (gtk_toggle_button_get_active (button)) {
4120 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4121 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4122 if ((node_button != button) &&
4123 gtk_toggle_button_get_active (node_button)) {
4124 gtk_toggle_button_set_active (node_button, FALSE);
4127 helper->current_format = button;
4129 gboolean found = FALSE;
4130 /* If no one is active, activate it again */
4131 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4132 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4133 if (gtk_toggle_button_get_active (node_button)) {
4139 gtk_toggle_button_set_active (button, TRUE);
4146 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4151 GtkWidget *priority_hbox;
4152 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4153 GtkWidget *captioned;
4154 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4155 GtkWidget *format_hbox;
4156 GtkWidget *html_toggle, *text_toggle;
4157 ModestMsgEditWindowPrivate *priv;
4158 MessageSettingsHelper helper = {0,};
4160 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4161 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4162 helper.window = window;
4163 helper.priority_group = NULL;
4164 helper.format_group = NULL;
4166 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4167 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4169 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4170 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4171 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4172 vbox = gtk_vbox_new (FALSE, 0);
4173 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4174 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4175 gtk_container_add (GTK_CONTAINER (align), vbox);
4176 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4177 gtk_widget_show (align);
4178 gtk_widget_show (vbox);
4180 /* Priority toggles */
4181 priority_hbox = gtk_hbox_new (TRUE, 0);
4182 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4183 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4184 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4185 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4186 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4187 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4188 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4189 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4190 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4191 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4192 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4193 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4194 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4195 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4196 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4197 gtk_widget_show_all (priority_hbox);
4198 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4199 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4200 gtk_widget_show (captioned);
4201 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4203 /* format toggles */
4204 format_hbox = gtk_hbox_new (TRUE, 0);
4205 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4206 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4207 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4208 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4209 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4210 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4211 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4212 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4213 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4214 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4215 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4216 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4217 gtk_widget_show_all (format_hbox);
4218 gtk_widget_show (format_hbox);
4219 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4222 g_object_unref (title_sizegroup);
4223 g_object_unref (value_sizegroup);
4225 /* Set current values */
4226 switch (priv->priority_flags) {
4227 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4228 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4229 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4231 case TNY_HEADER_FLAG_LOW_PRIORITY:
4232 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4233 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4236 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4237 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4241 switch (modest_msg_edit_window_get_format (window)) {
4242 case MODEST_MSG_EDIT_FORMAT_TEXT:
4243 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4244 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4246 case MODEST_MSG_EDIT_FORMAT_HTML:
4248 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4249 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4253 /* Signal connects */
4254 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4255 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4256 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4257 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4258 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4260 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4261 GTK_WINDOW (dialog), GTK_WINDOW (window));
4263 /* Save settings if the user clicked on done */
4264 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4265 TnyHeaderFlags flags;
4266 ModestMsgEditFormat old_format, new_format;
4268 /* Set priority flags */
4269 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4270 if (priv->priority_flags != flags)
4271 modest_msg_edit_window_set_priority_flags (window, flags);
4273 /* Set edit format */
4274 old_format = modest_msg_edit_window_get_format (window);
4275 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4276 if (old_format != new_format) {
4277 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4278 modest_msg_edit_window_set_file_format (window, file_format);
4282 gtk_widget_destroy (dialog);
4283 g_slist_free (helper.priority_group);
4287 on_message_settings (GtkAction *action,
4288 ModestMsgEditWindow *window)
4290 modest_msg_edit_window_show_msg_settings_dialog (window);
4294 on_cc_button_toggled (HildonCheckButton *button,
4295 ModestMsgEditWindow *window)
4297 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4299 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4300 hildon_check_button_get_active (button));
4304 on_bcc_button_toggled (HildonCheckButton *button,
4305 ModestMsgEditWindow *window)
4307 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4309 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4310 hildon_check_button_get_active (button));
4314 setup_menu (ModestMsgEditWindow *self)
4316 ModestMsgEditWindowPrivate *priv = NULL;
4318 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4322 /* Settings menu buttons */
4323 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4324 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4326 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4327 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4328 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4330 priv->cc_button = hildon_check_button_new (0);
4331 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4332 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4334 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4336 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4337 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4338 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4339 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4341 priv->bcc_button = hildon_check_button_new (0);
4342 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4343 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4345 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4347 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4348 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4349 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4350 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4352 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4353 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4354 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4355 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4356 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4358 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4359 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4360 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4361 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4362 APP_MENU_CALLBACK (on_message_settings),
4364 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4365 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4370 emit_open_addressbook (GtkButton *button,
4371 ModestRecptEditor *editor)
4373 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4377 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4378 const gchar *label, GtkWidget *control)
4380 GtkWidget *abook_button;
4383 GtkWidget *label_widget;
4385 box = gtk_hbox_new (FALSE, 0);
4387 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4388 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4390 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4391 label_widget = gtk_label_new (label);
4392 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4393 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4395 gtk_container_add (GTK_CONTAINER (align), abook_button);
4396 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4397 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4398 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4399 if (title_size_group)
4400 gtk_size_group_add_widget (title_size_group, label_widget);
4401 if (value_size_group)
4402 gtk_size_group_add_widget (value_size_group, control);
4404 g_signal_connect (G_OBJECT (abook_button), "clicked",
4405 G_CALLBACK (emit_open_addressbook), control);
4411 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4413 ModestMsgEditWindowPrivate *priv = NULL;
4415 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4417 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4418 priv->max_chars_banner = NULL;