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 #include "widgets/modest-msg-edit-window-ui.h"
74 #include <libgnomevfs/gnome-vfs-mime.h>
75 #include <modest-utils.h>
76 #include "modest-maemo-utils.h"
77 #include <modest-ui-constants.h>
78 #include "modest-color-button.h"
80 #ifdef MODEST_USE_CALENDAR_WIDGETS
81 #include <calendar-ui-widgets.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 0
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
91 #define ATTACHMENT_BUTTON_WIDTH 118
92 #define MAX_FROM_VALUE 36
93 #define MAX_BODY_LENGTH 128*1024
94 #define MAX_BODY_LINES 2048
96 static gboolean is_wp_text_buffer_started = FALSE;
98 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
99 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
100 static void modest_msg_edit_window_finalize (GObject *obj);
102 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
103 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
104 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
107 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
108 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
109 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
110 GtkTextIter *start, GtkTextIter *end,
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void body_insert_text (GtkTextBuffer *buffer,
114 GtkTextIter *location,
117 ModestMsgEditWindow *window);
118 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
119 static void subject_field_insert_text (GtkEditable *editable,
121 gint new_text_length,
123 ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
128 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
129 ModestRecptEditor *editor);
130 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
131 ModestMsgEditWindow *window);
133 /* ModestWindow methods implementation */
134 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
135 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
136 gboolean show_toolbar);
137 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
139 ModestMsgEditWindow *window);
140 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
141 static void subject_field_move_cursor (GtkEntry *entry,
142 GtkMovementStep step,
146 static void update_window_title (ModestMsgEditWindow *window);
149 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
150 ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
155 GtkTextIter *match_start,
156 GtkTextIter *match_end);
158 static void remove_tags (WPTextBuffer *buffer);
160 static void on_account_removed (TnyAccountStore *account_store,
164 static void init_window (ModestMsgEditWindow *obj);
166 gboolean scroll_drag_timeout (gpointer userdata);
167 static void correct_scroll (ModestMsgEditWindow *w);
168 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
169 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void text_buffer_mark_set (GtkTextBuffer *buffer,
174 ModestMsgEditWindow *userdata);
175 static void on_show_toolbar_button_toggled (HildonCheckButton *button,
176 ModestMsgEditWindow *window);
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;
274 GtkWidget *bottom_send_button;
275 GtkWidget *bottom_send_button_container;
277 GtkWidget *cc_caption;
278 GtkWidget *bcc_caption;
279 gboolean update_caption_visibility;
280 GtkWidget *attachments_caption;
282 GtkTextBuffer *text_buffer;
284 GtkWidget *font_size_toolitem;
285 GtkWidget *font_face_toolitem;
286 GtkWidget *font_color_button;
287 GtkWidget *font_color_toolitem;
288 GSList *font_items_group;
289 GtkTreeModel *faces_model;
290 gint current_face_index;
291 GtkWidget *font_tool_button_label;
292 GtkTreeModel *sizes_model;
293 gint current_size_index;
294 GtkWidget *size_tool_button_label;
296 GtkWidget *find_toolbar;
299 GtkWidget *font_dialog;
302 guint correct_scroll_idle;
303 guint scroll_drag_timeout_id;
307 TnyList *attachments;
312 TnyHeaderFlags priority_flags;
314 gboolean can_undo, can_redo;
315 gulong clipboard_change_handler_id;
316 gulong default_clipboard_change_handler_id;
317 gulong account_removed_handler_id;
318 guint clipboard_owner_idle;
319 gchar *clipboard_text;
328 GtkWidget *cc_button;
329 GtkWidget *bcc_button;
330 GtkWidget *show_toolbar_button;
332 GtkWidget *max_chars_banner;
334 GtkWidget *brand_icon;
335 GtkWidget *brand_label;
336 GtkWidget *brand_container;
338 TnyList *custom_header_pairs;
341 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
342 MODEST_TYPE_MSG_EDIT_WINDOW, \
343 ModestMsgEditWindowPrivate))
345 static GtkWindowClass *parent_class = NULL;
347 /* uncomment the following if you have defined any signals */
348 /* static guint signals[LAST_SIGNAL] = {0}; */
351 modest_msg_edit_window_get_type (void)
353 static GType my_type = 0;
355 static const GTypeInfo my_info = {
356 sizeof(ModestMsgEditWindowClass),
357 NULL, /* base init */
358 NULL, /* base finalize */
359 (GClassInitFunc) modest_msg_edit_window_class_init,
360 NULL, /* class finalize */
361 NULL, /* class data */
362 sizeof(ModestMsgEditWindow),
364 (GInstanceInitFunc) modest_msg_edit_window_init,
367 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
368 "ModestMsgEditWindow",
376 save_state (ModestWindow *self)
378 modest_widget_memory_save (modest_runtime_get_conf(),
379 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
384 restore_settings (ModestMsgEditWindow *self)
386 ModestConf *conf = NULL;
388 conf = modest_runtime_get_conf ();
390 /* Dim at start clipboard actions */
391 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
396 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
398 GObjectClass *gobject_class;
399 ModestWindowClass *modest_window_class;
400 gobject_class = (GObjectClass*) klass;
401 modest_window_class = (ModestWindowClass*) klass;
403 parent_class = g_type_class_peek_parent (klass);
404 gobject_class->finalize = modest_msg_edit_window_finalize;
406 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
407 modest_window_class->save_state_func = save_state;
408 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
410 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
414 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
416 ModestMsgEditWindowPrivate *priv;
417 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
419 priv->msg_body = NULL;
420 priv->from_field = NULL;
421 priv->to_field = NULL;
422 priv->cc_field = NULL;
423 priv->bcc_field = NULL;
424 priv->subject_field = NULL;
425 priv->attachments = TNY_LIST (tny_simple_list_new ());
426 priv->images = TNY_LIST (tny_simple_list_new ());
427 priv->images_size = 0;
428 priv->images_count = 0;
431 priv->cc_caption = NULL;
432 priv->bcc_caption = NULL;
433 priv->update_caption_visibility = FALSE;
435 priv->priority_flags = 0;
437 priv->find_toolbar = NULL;
438 priv->last_search = NULL;
440 priv->draft_msg = NULL;
441 priv->outbox_msg = NULL;
442 priv->msg_uid = NULL;
444 priv->can_undo = FALSE;
445 priv->can_redo = FALSE;
446 priv->clipboard_change_handler_id = 0;
447 priv->default_clipboard_change_handler_id = 0;
448 priv->account_removed_handler_id = 0;
449 priv->clipboard_owner_idle = 0;
450 priv->clipboard_text = NULL;
453 priv->scroll_drag_timeout_id = 0;
454 priv->correct_scroll_idle = 0;
455 priv->last_upper = 0.0;
457 priv->font_dialog = NULL;
458 priv->app_menu = NULL;
460 priv->references = NULL;
461 priv->in_reply_to = NULL;
462 priv->max_chars_banner = NULL;
463 priv->custom_header_pairs = TNY_LIST (tny_simple_list_new ());
465 if (!is_wp_text_buffer_started) {
466 is_wp_text_buffer_started = TRUE;
467 wp_text_buffer_library_init ();
472 hildon_program_add_window (hildon_program_get_instance(),
477 multimailbox_get_default_mailbox (const gchar *account_name)
479 gchar *transport_account;
480 gchar *result = NULL;
482 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
484 TNY_ACCOUNT_TYPE_TRANSPORT);
485 if (transport_account) {
487 ModestProtocolRegistry *registry;
489 registry = modest_runtime_get_protocol_registry ();
491 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
492 MODEST_ACCOUNT_PROTO, TRUE);
494 ModestProtocol *protocol =
495 modest_protocol_registry_get_protocol_by_name (registry,
496 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
498 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
499 ModestPairList *pair_list;
501 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
504 ModestPair *pair = (ModestPair *) pair_list->data;
505 result = g_strdup ((const gchar *) pair->first);
506 modest_pair_list_free (pair_list);
517 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
519 static ModestPairList*
520 get_transports (void)
522 GSList *transports = NULL;
524 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
525 GSList *accounts = modest_account_mgr_account_names (account_mgr,
526 TRUE /* only enabled accounts. */);
528 GSList *cursor = accounts;
530 gchar *account_name = cursor->data;
533 gchar *transport_account;
534 gboolean multi_mailbox = FALSE;
535 ModestProtocol *protocol = NULL;
537 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
539 transport_account = modest_account_mgr_get_server_account_name
540 (modest_runtime_get_account_mgr (),
542 TNY_ACCOUNT_TYPE_TRANSPORT);
543 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
544 ModestPairList *pair_list;
545 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
548 transports = g_slist_concat (transports, pair_list);
549 multi_mailbox = TRUE;
554 if (!multi_mailbox) {
555 gchar *from_string = NULL;
557 from_string = modest_account_mgr_get_from_string (account_mgr,
559 if (from_string && account_name) {
560 gchar *name = account_name;
561 ModestPair *pair = modest_pair_new ((gpointer) name,
562 (gpointer) from_string , TRUE);
563 transports = g_slist_prepend (transports, pair);
568 cursor = cursor->next;
570 g_slist_free (accounts); /* only free the accounts, not the elements,
571 * because they are used in the pairlist */
575 static void window_focus (GtkWindow *window,
579 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
583 scroll_drag_timeout (gpointer userdata)
585 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
586 ModestMsgEditWindowPrivate *priv;
588 /* It could happen that the window was already closed */
589 if (!GTK_WIDGET_VISIBLE (win))
592 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
594 correct_scroll_without_drag_check (win, TRUE);
596 priv->scroll_drag_timeout_id = 0;
602 correct_scroll_without_drag_check_idle (gpointer userdata)
604 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
605 ModestMsgEditWindowPrivate *priv;
607 GdkRectangle rectangle;
608 gint offset_min, offset_max;
612 /* It could happen that the window was already closed */
613 if (!GTK_WIDGET_VISIBLE (w))
616 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
618 insert = gtk_text_buffer_get_insert (priv->text_buffer);
619 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
621 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
622 offset_min = priv->msg_body->allocation.y + rectangle.y;
623 offset_max = offset_min + rectangle.height;
625 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
626 offset_min = MAX (offset_min - 48, 0);
627 offset_max = MIN (offset_max + 48, vadj->upper);
629 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
631 priv->correct_scroll_idle = 0;
636 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
638 ModestMsgEditWindowPrivate *priv;
640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
642 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
645 if (priv->correct_scroll_idle > 0) {
649 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
650 (GSourceFunc) correct_scroll_without_drag_check_idle,
656 correct_scroll (ModestMsgEditWindow *w)
658 ModestMsgEditWindowPrivate *priv;
660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
661 if (gtk_grab_get_current () == priv->msg_body) {
662 if (priv->scroll_drag_timeout_id == 0) {
663 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
665 (GSourceFunc) scroll_drag_timeout,
672 correct_scroll_without_drag_check (w, TRUE);
676 text_buffer_end_user_action (GtkTextBuffer *buffer,
677 ModestMsgEditWindow *userdata)
680 correct_scroll (userdata);
684 text_buffer_mark_set (GtkTextBuffer *buffer,
687 ModestMsgEditWindow *userdata)
689 gtk_text_buffer_begin_user_action (buffer);
690 gtk_text_buffer_end_user_action (buffer);
694 cut_clipboard_check (GtkTextView *text_view,
697 GtkTextBuffer *buffer;
699 buffer = gtk_text_view_get_buffer (text_view);
700 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
701 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
706 copy_clipboard_check (GtkTextView *text_view,
709 GtkTextBuffer *buffer;
711 buffer = gtk_text_view_get_buffer (text_view);
712 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
713 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
718 attachment_deleted (ModestAttachmentsView *attachments_view,
721 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
726 body_size_request (GtkWidget *body,
730 ModestMsgEditWindowPrivate *priv;
733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(user_data);
735 /* Make sure the body always get at least 70 pixels */
736 if (req->height < 70)
739 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
740 if (priv->header_box->allocation.height + req->height > GTK_WIDGET (user_data)->allocation.height) {
741 if (!GTK_WIDGET_VISIBLE (priv->bottom_send_button_container)) {
742 gtk_widget_show (priv->bottom_send_button_container);
745 if (GTK_WIDGET_VISIBLE (priv->bottom_send_button_container)) {
746 gtk_widget_hide (priv->bottom_send_button_container);
752 connect_signals (ModestMsgEditWindow *obj)
754 ModestMsgEditWindowPrivate *priv;
756 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
758 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
759 G_CALLBACK (text_buffer_refresh_attributes), obj);
760 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
761 G_CALLBACK (text_buffer_can_undo), obj);
762 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
763 G_CALLBACK (text_buffer_can_redo), obj);
764 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
765 G_CALLBACK (body_changed), obj);
766 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
767 G_CALLBACK (body_insert_text), obj);
768 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
769 G_CALLBACK (body_changed), obj);
770 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
771 G_CALLBACK (text_buffer_end_user_action), obj);
772 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
773 G_CALLBACK (text_buffer_mark_set), obj);
774 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
775 G_CALLBACK (text_buffer_apply_tag), obj);
776 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
777 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
778 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
779 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
780 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
781 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
783 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
784 G_CALLBACK (modest_ui_actions_on_send), obj);
786 g_signal_connect (G_OBJECT (priv->bottom_send_button), "clicked",
787 G_CALLBACK (modest_ui_actions_on_send), obj);
789 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
790 G_CALLBACK (from_field_changed), obj);
792 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
793 G_CALLBACK (msg_body_focus), obj);
794 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
795 G_CALLBACK (msg_body_focus), obj);
796 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
797 G_CALLBACK (body_size_request), obj);
798 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
799 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
800 "changed", G_CALLBACK (recpt_field_changed), obj);
801 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
802 "changed", G_CALLBACK (recpt_field_changed), obj);
803 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
804 "changed", G_CALLBACK (recpt_field_changed), obj);
805 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
806 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
807 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
809 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
810 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
812 priv->clipboard_change_handler_id =
813 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
814 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
815 priv->default_clipboard_change_handler_id =
816 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
817 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
819 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
820 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
821 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
825 init_wp_text_view_style ()
827 static gboolean initialized = FALSE;
830 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
836 init_window (ModestMsgEditWindow *obj)
838 GtkWidget *to_caption, *subject_caption;
839 GtkWidget *main_vbox;
840 ModestMsgEditWindowPrivate *priv;
841 GtkActionGroup *action_group;
842 ModestWindowPrivate *parent_priv;
843 GdkPixbuf *window_icon = NULL;
844 GError *error = NULL;
846 GtkSizeGroup *title_size_group;
847 GtkSizeGroup *value_size_group;
848 GtkWidget *window_box;
849 GtkWidget *window_align;
850 #if (GTK_MINOR_VERSION >= 10)
851 GdkAtom deserialize_type;
853 GtkWidget *from_send_hbox;
854 GtkWidget *send_icon;
855 GtkWidget *attachments_label;
856 GtkWidget *branding_box;
858 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
859 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
861 parent_priv->ui_manager = gtk_ui_manager_new();
862 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
863 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
865 /* Add common actions */
866 gtk_action_group_add_actions (action_group,
867 modest_msg_edit_action_entries,
868 G_N_ELEMENTS (modest_msg_edit_action_entries),
870 gtk_action_group_add_actions (action_group,
871 hildon2_msg_edit_action_entries,
872 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
874 gtk_action_group_add_toggle_actions (action_group,
875 modest_msg_edit_toggle_action_entries,
876 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
878 gtk_action_group_add_radio_actions (action_group,
879 modest_msg_edit_alignment_radio_action_entries,
880 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
882 G_CALLBACK (modest_ui_actions_on_change_justify),
884 gtk_action_group_add_radio_actions (action_group,
885 modest_msg_edit_priority_action_entries,
886 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
888 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
890 gtk_action_group_add_radio_actions (action_group,
891 modest_msg_edit_file_format_action_entries,
892 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
893 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
894 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
896 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
897 g_object_unref (action_group);
899 /* Load the UI definition */
900 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
903 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
904 g_clear_error (&error);
907 /* Add accelerators */
908 gtk_window_add_accel_group (GTK_WINDOW (obj),
909 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
911 parent_priv->menubar = NULL;
913 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
914 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
916 /* Note: This ModestPairList* must exist for as long as the picker
917 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
918 * so it can't know how to manage its memory. */
919 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
920 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
922 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
923 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
924 _("mail_va_from"), priv->from_field);
925 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
926 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
927 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
929 priv->to_field = modest_recpt_editor_new ();
930 priv->cc_field = modest_recpt_editor_new ();
931 priv->bcc_field = modest_recpt_editor_new ();
932 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
933 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
934 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
935 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
936 priv->priority_icon = gtk_image_new ();
937 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
938 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
939 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
940 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
941 hildon_entry_set_placeholder ((HildonEntry *) priv->subject_field, _("mail_va_no_subject"));
942 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
943 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
944 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
945 priv->attachments_view = modest_attachments_view_new (NULL);
946 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
947 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
949 priv->header_box = gtk_vbox_new (FALSE, 0);
951 to_caption = _create_addressbook_box
952 (title_size_group, value_size_group,
953 _("mail_va_to"), priv->to_field);
954 priv->cc_caption = _create_addressbook_box
955 (title_size_group, value_size_group,
956 _("mail_va_cc"), priv->cc_field);
957 priv->bcc_caption = _create_addressbook_box
958 (title_size_group, value_size_group,
959 _("mail_va_hotfix1"), priv->bcc_field);
960 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
961 _("mail_va_subject"), FALSE, priv->subject_box);
962 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
963 _("mail_va_attachment"),
965 priv->attachments_view,
966 HILDON_SIZE_AUTO_WIDTH |
967 HILDON_SIZE_AUTO_HEIGHT);
968 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
969 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
972 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
973 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
974 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
975 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
977 priv->bottom_send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
978 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
979 gtk_container_add (GTK_CONTAINER (priv->bottom_send_button), send_icon);
980 gtk_widget_set_size_request (GTK_WIDGET (priv->bottom_send_button), 148, -1);
982 priv->bottom_send_button_container = gtk_hbox_new (FALSE, 0);
983 gtk_widget_show (priv->bottom_send_button_container);
984 gtk_box_pack_end (GTK_BOX (priv->bottom_send_button_container), priv->bottom_send_button, FALSE, FALSE, 0);
985 gtk_widget_show (priv->bottom_send_button_container);
987 g_object_unref (title_size_group);
988 g_object_unref (value_size_group);
990 priv->brand_icon = gtk_image_new ();
991 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
992 priv->brand_label = gtk_label_new (NULL);
993 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
994 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
995 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
996 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
998 from_send_hbox = gtk_hbox_new (FALSE, 0);
999 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
1000 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1002 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1003 gtk_widget_show (branding_box);
1004 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1005 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1007 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1008 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1009 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1010 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1013 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1014 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1015 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1016 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1017 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1018 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1019 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1020 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1022 init_wp_text_view_style ();
1024 priv->msg_body = modest_wp_text_view_new ();
1027 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1028 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1029 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1030 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1031 #if (GTK_MINOR_VERSION >= 10)
1032 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1033 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1035 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1036 deserialize_type, TRUE);
1038 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1040 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1041 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1043 priv->pannable = hildon_pannable_area_new ();
1045 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1047 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1048 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1049 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), MODEST_MARGIN_HALF, 0,
1050 MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1052 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1053 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1054 gtk_box_pack_start (GTK_BOX (main_vbox), priv->bottom_send_button_container, FALSE, FALSE, 0);
1055 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1057 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1058 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1060 window_box = gtk_vbox_new (FALSE, 0);
1061 gtk_container_add (GTK_CONTAINER(obj), window_box);
1063 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1065 /* Set window icon */
1066 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1068 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1069 g_object_unref (window_icon);
1074 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1076 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1078 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1079 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1080 priv->clipboard_change_handler_id))
1081 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1082 priv->clipboard_change_handler_id);
1083 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1084 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1085 priv->default_clipboard_change_handler_id))
1086 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1087 priv->default_clipboard_change_handler_id);
1089 if (priv->account_removed_handler_id &&
1090 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1091 priv->account_removed_handler_id))
1092 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1093 priv->account_removed_handler_id);
1097 modest_msg_edit_window_finalize (GObject *obj)
1099 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1101 g_object_unref (priv->custom_header_pairs);
1103 if (priv->max_chars_banner) {
1104 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1105 priv->max_chars_banner = FALSE;
1108 /* Sanity check: shouldn't be needed, the window mgr should
1109 call this function before */
1110 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1112 if (priv->font_dialog != NULL) {
1113 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1116 if (priv->clipboard_text != NULL) {
1117 g_free (priv->clipboard_text);
1118 priv->clipboard_text = NULL;
1121 if (priv->draft_msg != NULL) {
1122 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1123 if (TNY_IS_HEADER (header)) {
1124 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1125 modest_window_mgr_unregister_header (mgr, header);
1127 g_object_unref (priv->draft_msg);
1128 priv->draft_msg = NULL;
1130 if (priv->outbox_msg != NULL) {
1131 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1132 if (TNY_IS_HEADER (header)) {
1133 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1134 modest_window_mgr_unregister_header (mgr, header);
1136 g_object_unref (priv->outbox_msg);
1137 priv->outbox_msg = NULL;
1139 if (priv->correct_scroll_idle > 0) {
1140 g_source_remove (priv->correct_scroll_idle);
1141 priv->correct_scroll_idle = 0;
1143 if (priv->scroll_drag_timeout_id > 0) {
1144 g_source_remove (priv->scroll_drag_timeout_id);
1145 priv->scroll_drag_timeout_id = 0;
1147 if (priv->clipboard_owner_idle > 0) {
1148 g_source_remove (priv->clipboard_owner_idle);
1149 priv->clipboard_owner_idle = 0;
1151 if (priv->original_account_name)
1152 g_free (priv->original_account_name);
1153 if (priv->original_mailbox)
1154 g_free (priv->original_mailbox);
1155 g_free (priv->msg_uid);
1156 g_free (priv->last_search);
1157 g_free (priv->references);
1158 g_free (priv->in_reply_to);
1159 g_object_unref (priv->attachments);
1160 g_object_unref (priv->images);
1162 /* This had to stay alive for as long as the picker that used it: */
1163 modest_pair_list_free (priv->from_field_protos);
1165 G_OBJECT_CLASS(parent_class)->finalize (obj);
1169 pixbuf_size_prepared (GdkPixbufLoader *loader,
1172 ModestMsgEditWindow *self)
1174 gint new_height, new_width;
1177 new_height = height;
1181 if (width > IMAGE_MAX_WIDTH) {
1182 new_height = height * IMAGE_MAX_WIDTH / width;
1183 new_width = IMAGE_MAX_WIDTH;
1186 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1190 pixbuf_from_stream (TnyStream *stream,
1191 const gchar *mime_type,
1192 guint64 *stream_size,
1193 ModestMsgEditWindow *self)
1195 GdkPixbufLoader *loader;
1198 GError *error = NULL;
1202 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1204 if (loader == NULL) {
1209 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1211 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1213 tny_stream_reset (TNY_STREAM (stream));
1214 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1215 unsigned char read_buffer[128];
1217 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1219 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1222 /* Allow some UI responsiveness */
1223 while (gtk_events_pending ())
1224 gtk_main_iteration ();
1226 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1228 gdk_pixbuf_loader_close (loader, &error);
1231 g_error_free (error);
1232 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1234 g_object_ref (pixbuf);
1235 g_object_unref (loader);
1240 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1241 GdkPixbuf *new_pixbuf;
1243 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1244 gdk_pixbuf_get_width (pixbuf);
1245 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1246 g_object_unref (pixbuf);
1247 pixbuf = new_pixbuf;
1251 *stream_size = size;
1257 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1259 ModestMsgEditWindowPrivate *priv;
1262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1264 g_object_ref (self);
1265 for (iter = tny_list_create_iterator (attachments);
1266 !tny_iterator_is_done (iter);
1267 tny_iterator_next (iter)) {
1268 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1269 const gchar *cid = tny_mime_part_get_content_id (part);
1270 const gchar *mime_type = tny_mime_part_get_content_type (part);
1271 if ((cid != NULL)&&(mime_type != NULL)) {
1272 guint64 stream_size;
1273 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1274 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1277 g_object_unref (stream);
1279 if (pixbuf != NULL) {
1280 priv->images_count ++;
1281 priv->images_size += stream_size;
1282 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1283 g_object_unref (pixbuf);
1286 g_object_unref (part);
1288 g_object_unref (iter);
1289 g_object_unref (self);
1293 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1295 TnyMimePart *parent = NULL;
1296 const gchar *content_type = NULL;
1297 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1299 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1301 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1302 parent = g_object_ref (msg);
1303 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1304 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1307 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1308 iter = tny_list_create_iterator (parts);
1309 while (!tny_iterator_is_done (iter)) {
1311 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1312 content_type = tny_mime_part_get_content_type (part);
1313 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1317 g_object_unref (part);
1319 tny_iterator_next (iter);
1321 g_object_unref (iter);
1322 g_object_unref (parts);
1325 if (parent != NULL) {
1326 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1329 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1330 iter = tny_list_create_iterator (parts);
1331 while (!tny_iterator_is_done (iter)) {
1333 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1334 content_type = tny_mime_part_get_content_type (part);
1335 if (content_type && g_str_has_prefix (content_type, "image/")) {
1336 tny_list_prepend (priv->images, (GObject *) part);
1338 g_object_unref (part);
1339 tny_iterator_next (iter);
1341 g_object_unref (iter);
1342 g_object_unref (parts);
1343 g_object_unref (parent);
1348 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1351 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1353 for (iter = tny_list_create_iterator (attachments) ;
1354 !tny_iterator_is_done (iter);
1355 tny_iterator_next (iter)) {
1356 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1357 const gchar *cid = tny_mime_part_get_content_id (part);
1359 char *invalid = NULL;
1360 gint int_cid = strtol (cid, &invalid, 10);
1361 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1362 priv->next_cid = int_cid + 1;
1365 g_object_unref (part);
1367 g_object_unref (iter);
1371 remove_non_calendar_headers (TnyList *list,
1373 gpointer match_data)
1375 if (g_str_has_prefix (tny_pair_get_name (TNY_PAIR (item)), "X-as"))
1382 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1385 gchar *to, *cc, *bcc, *subject;
1387 ModestMsgEditWindowPrivate *priv;
1388 ModestWindowPrivate *parent_priv;
1390 TnyHeaderFlags priority_flags;
1391 TnyFolder *msg_folder;
1392 gboolean is_html = FALSE;
1393 gboolean field_view_set;
1394 TnyList *orig_header_pairs;
1396 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1397 g_return_if_fail (TNY_IS_MSG (msg));
1399 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1400 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1402 header = tny_msg_get_header (msg);
1403 to = tny_header_dup_to (header);
1404 cc = tny_header_dup_cc (header);
1405 bcc = tny_header_dup_bcc (header);
1406 subject = tny_header_dup_subject (header);
1408 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1409 priority_flags = tny_header_get_priority (header);
1412 gchar *quoted_names = modest_text_utils_quote_names (to);
1413 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1414 g_free (quoted_names);
1417 field_view_set = TRUE;
1419 gchar *quoted_names = modest_text_utils_quote_names (cc);
1420 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1421 g_free (quoted_names);
1422 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1423 gtk_widget_show (priv->cc_caption);
1424 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1425 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1426 gtk_widget_hide (priv->cc_caption);
1427 field_view_set = FALSE;
1429 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1431 field_view_set = TRUE;
1433 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1434 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1435 g_free (quoted_names);
1436 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1437 gtk_widget_show (priv->bcc_caption);
1438 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1439 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1440 gtk_widget_hide (priv->bcc_caption);
1441 field_view_set = FALSE;
1443 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1447 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1448 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1451 update_window_title (self);
1453 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1454 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1456 if ((body == NULL)||(body[0] == '\0')) {
1458 body = modest_text_utils_convert_to_html ("");
1461 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1462 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1465 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1468 /* Add attachments to the view */
1469 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1470 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1471 if (tny_list_get_length (priv->attachments) == 0) {
1472 gtk_widget_hide (priv->attachments_caption);
1474 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1475 gtk_widget_show_all (priv->attachments_caption);
1477 get_related_images (self, msg);
1478 update_next_cid (self, priv->attachments);
1479 update_next_cid (self, priv->images);
1480 replace_with_images (self, priv->images);
1482 if (preserve_is_rich && !is_html) {
1483 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1484 /* Get the default format required from configuration */
1485 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1486 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1489 /* Set the default focus depending on having already a To: field or not */
1490 if ((!to)||(*to == '\0')) {
1491 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1493 gtk_widget_grab_focus (priv->msg_body);
1496 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1498 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1499 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1501 modest_msg_edit_window_set_modified (self, FALSE);
1503 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1504 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1505 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1506 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1508 if (priv->msg_uid) {
1509 g_free (priv->msg_uid);
1510 priv->msg_uid = NULL;
1513 /* we should set a reference to the incoming message if it is a draft */
1514 msg_folder = tny_msg_get_folder (msg);
1516 if (modest_tny_folder_is_local_folder (msg_folder)) {
1517 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1518 if (type == TNY_FOLDER_TYPE_INVALID)
1519 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1521 if (type == TNY_FOLDER_TYPE_DRAFTS)
1522 priv->draft_msg = g_object_ref(msg);
1523 if (type == TNY_FOLDER_TYPE_OUTBOX)
1524 priv->outbox_msg = g_object_ref(msg);
1525 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1527 g_object_unref (msg_folder);
1530 /* Copy orig headers used by ActiveSync calendar invitations */
1531 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1532 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1533 tny_list_remove_matches (orig_header_pairs, remove_non_calendar_headers, NULL);
1534 if (tny_list_get_length (orig_header_pairs) > 0)
1535 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1536 g_object_unref (orig_header_pairs);
1545 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1547 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1548 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1549 GtkWidget *placeholder;
1550 GtkWidget *tool_item;
1555 GtkWidget *sizes_menu;
1556 GtkWidget *fonts_menu;
1562 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1563 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1564 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1565 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1567 /* Font color placeholder */
1568 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1569 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1572 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1573 priv->font_color_button = modest_color_button_new ();
1574 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1575 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1576 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1577 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1578 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1579 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1580 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1581 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1583 G_CALLBACK (modest_msg_edit_window_color_button_change),
1586 /* Font size and face placeholder */
1587 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1588 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1590 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1591 priv->size_tool_button_label = gtk_label_new (NULL);
1592 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1593 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1594 size_text, "</span>", NULL);
1595 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1596 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1598 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1599 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1600 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1601 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1602 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1603 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1604 gtk_widget_set_sensitive (arrow, FALSE);
1605 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1606 sizes_menu = gtk_menu_new ();
1607 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1608 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1611 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1612 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1614 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1618 if (wp_font_size[size_index] == 12)
1619 priv->current_size_index = size_index;
1623 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1624 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1625 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1626 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1627 priv->font_size_toolitem = tool_item;
1630 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1631 priv->font_tool_button_label = gtk_label_new (NULL);
1632 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1633 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1634 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1636 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1637 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1638 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1639 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1640 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1641 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1642 gtk_widget_set_sensitive (arrow, FALSE);
1643 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1644 fonts_menu = gtk_menu_new ();
1645 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1646 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1649 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1651 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1652 0, wp_get_font_name (font_index),
1655 if (font_index == DEFAULT_FONT)
1656 priv->current_face_index = font_index;
1658 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1659 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1660 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1661 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1662 priv->font_face_toolitem = tool_item;
1664 /* Set expand and homogeneous for remaining items */
1665 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1666 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1667 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1668 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1669 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1670 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1671 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1672 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1673 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1675 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1676 will not show the tool items added to the placeholders) */
1677 gtk_widget_show_all (parent_priv->toolbar);
1679 /* Set the no show all *after* showing all items. We do not
1680 want the toolbar to be shown with a show all because it
1681 could go against the gconf setting regarding showing or not
1682 the toolbar of the editor window */
1683 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1689 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1692 ModestWindowPrivate *parent_priv;
1693 ModestMsgEditWindowPrivate *priv;
1694 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1695 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1696 ModestWindowMgr *mgr = NULL;
1698 g_return_val_if_fail (msg, NULL);
1699 g_return_val_if_fail (account_name, NULL);
1701 mgr = modest_runtime_get_window_mgr ();
1703 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1706 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1708 /* Menubar. Update the state of some toggles */
1709 priv->from_field_protos = get_transports ();
1710 priv->original_mailbox = NULL;
1711 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1712 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1713 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1714 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1715 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1716 priv->original_mailbox = g_strdup (mailbox);
1717 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1718 /* We set the first mailbox as the active mailbox */
1719 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1720 if (priv->original_mailbox != NULL)
1721 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1722 (gpointer) priv->original_mailbox);
1724 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1725 (gpointer) account_name);
1727 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1729 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1730 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1731 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1733 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1734 hildon_touch_selector_get_current_text
1735 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1736 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1737 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1740 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1742 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1744 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1745 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1747 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1749 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1750 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1751 /* Add common dimming rules */
1752 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1753 modest_msg_edit_window_toolbar_dimming_entries,
1754 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1755 MODEST_WINDOW (obj));
1756 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1757 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1758 MODEST_WINDOW (obj));
1759 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1760 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1761 MODEST_WINDOW (obj));
1762 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1763 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1764 MODEST_WINDOW (obj));
1765 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1766 G_CALLBACK (modest_ui_dimming_rules_on_send),
1767 MODEST_WINDOW (obj));
1768 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->bottom_send_button,
1769 G_CALLBACK (modest_ui_dimming_rules_on_send),
1770 MODEST_WINDOW (obj));
1771 /* Insert dimming rules group for this window */
1772 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1773 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1775 /* Setup app menu */
1776 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1778 /* Checks the dimming rules */
1779 g_object_unref (toolbar_rules_group);
1780 g_object_unref (clipboard_rules_group);
1781 gtk_widget_hide (priv->priority_icon);
1782 gtk_widget_queue_resize (priv->subject_box);
1783 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1785 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1787 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1788 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1789 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1790 priv->update_caption_visibility = TRUE;
1792 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1794 /* Track account-removed signal, this window should be closed
1795 in the case we're creating a mail associated to the account
1797 priv->account_removed_handler_id =
1798 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1800 G_CALLBACK(on_account_removed),
1803 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1805 return (ModestWindow*) obj;
1809 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1811 GString **string_buffer = (GString **) user_data;
1813 *string_buffer = g_string_append (*string_buffer, buffer);
1819 * @result: A new string which should be freed with g_free().
1822 get_formatted_data (ModestMsgEditWindow *edit_window)
1824 ModestMsgEditWindowPrivate *priv;
1825 GString *string_buffer = g_string_new ("");
1827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1829 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1831 modest_text_utils_hyperlinkify (string_buffer);
1833 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1835 return g_string_free (string_buffer, FALSE);
1840 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1843 const gchar *account_name;
1844 ModestMsgEditWindowPrivate *priv;
1845 TnyIterator *att_iter;
1846 const gchar *picker_active_id;
1848 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1850 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1852 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1853 g_return_val_if_fail (picker_active_id, NULL);
1854 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1856 /* don't free these (except from) */
1857 data = g_slice_new0 (MsgData);
1858 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1859 data->account_name = g_strdup (account_name);
1860 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1861 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1862 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1863 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1864 data->references = g_strdup (priv->references);
1865 data->in_reply_to = g_strdup (priv->in_reply_to);
1866 if (priv->draft_msg) {
1867 data->draft_msg = g_object_ref (priv->draft_msg);
1868 } else if (priv->outbox_msg) {
1869 data->draft_msg = g_object_ref (priv->outbox_msg);
1871 data->draft_msg = NULL;
1874 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1876 gtk_text_buffer_get_bounds (buf, &b, &e);
1877 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1879 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1880 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1882 data->html_body = NULL;
1884 /* deep-copy the data */
1885 att_iter = tny_list_create_iterator (priv->attachments);
1886 data->attachments = NULL;
1887 while (!tny_iterator_is_done (att_iter)) {
1888 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1889 if (!(TNY_IS_MIME_PART(part))) {
1890 g_warning ("strange data in attachment list");
1891 g_object_unref (part);
1892 tny_iterator_next (att_iter);
1895 data->attachments = g_list_append (data->attachments,
1897 tny_iterator_next (att_iter);
1899 g_object_unref (att_iter);
1901 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1902 att_iter = tny_list_create_iterator (priv->images);
1903 data->images = NULL;
1904 while (!tny_iterator_is_done (att_iter)) {
1905 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1907 if (!(TNY_IS_MIME_PART(part))) {
1908 g_warning ("strange data in attachment list");
1909 g_object_unref (part);
1910 tny_iterator_next (att_iter);
1913 cid = tny_mime_part_get_content_id (part);
1915 gchar *image_tag_id;
1916 GtkTextTag *image_tag;
1918 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1919 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1920 g_free (image_tag_id);
1922 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1924 ((gtk_text_iter_has_tag (&iter, image_tag))||
1925 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1926 data->images = g_list_append (data->images,
1927 g_object_ref (part));
1929 g_object_unref (part);
1930 tny_iterator_next (att_iter);
1932 g_object_unref (att_iter);
1934 data->priority_flags = priv->priority_flags;
1935 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
1942 unref_gobject (GObject *obj, gpointer data)
1944 if (!G_IS_OBJECT(obj))
1946 g_object_unref (obj);
1950 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1953 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1961 g_free (data->from);
1962 g_free (data->subject);
1963 g_free (data->plain_body);
1964 g_free (data->html_body);
1965 g_free (data->account_name);
1966 g_free (data->references);
1967 g_free (data->in_reply_to);
1969 g_object_unref (data->custom_header_pairs);
1971 if (data->draft_msg != NULL) {
1972 g_object_unref (data->draft_msg);
1973 data->draft_msg = NULL;
1976 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1977 g_list_free (data->attachments);
1978 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1979 g_list_free (data->images);
1981 g_slice_free (MsgData, data);
1985 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1987 guint64 *parts_size)
1989 ModestMsgEditWindowPrivate *priv;
1991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1993 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1995 /* TODO: add images */
1996 *parts_size += priv->images_size;
1997 *parts_count += priv->images_count;
2002 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2005 ModestMsgEditWindowPrivate *priv = NULL;
2006 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2010 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2012 return MODEST_MSG_EDIT_FORMAT_HTML;
2014 return MODEST_MSG_EDIT_FORMAT_TEXT;
2018 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2019 ModestMsgEditFormat format)
2021 ModestMsgEditWindowPrivate *priv;
2022 ModestWindowPrivate *parent_priv;
2024 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2026 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2029 case MODEST_MSG_EDIT_FORMAT_HTML:
2030 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2031 update_signature (self, priv->last_from_account, priv->last_from_account);
2032 if (parent_priv->toolbar)
2033 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
2034 MODEST_MSG_EDIT_WINDOW (self));
2036 case MODEST_MSG_EDIT_FORMAT_TEXT:
2037 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2038 if (parent_priv->toolbar)
2039 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
2040 MODEST_MSG_EDIT_WINDOW (self));
2043 g_return_if_reached ();
2047 ModestMsgEditFormatState *
2048 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2050 ModestMsgEditFormatState *format_state = NULL;
2051 ModestMsgEditWindowPrivate *priv;
2052 WPTextBufferFormat *buffer_format;
2054 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2056 buffer_format = g_new0 (WPTextBufferFormat, 1);
2057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2059 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2061 format_state = g_new0 (ModestMsgEditFormatState, 1);
2062 format_state->bold = buffer_format->bold&0x1;
2063 format_state->italics = buffer_format->italic&0x1;
2064 format_state->bullet = buffer_format->bullet&0x1;
2065 format_state->color = buffer_format->color;
2066 format_state->font_size = buffer_format->font_size;
2067 format_state->font_family = wp_get_font_name (buffer_format->font);
2068 format_state->justification = buffer_format->justification;
2069 g_free (buffer_format);
2071 return format_state;
2076 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2077 const ModestMsgEditFormatState *format_state)
2079 ModestMsgEditWindowPrivate *priv;
2080 WPTextBufferFormat *buffer_format;
2081 WPTextBufferFormat *current_format;
2083 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2084 g_return_if_fail (format_state != NULL);
2086 buffer_format = g_new0 (WPTextBufferFormat, 1);
2087 current_format = g_new0 (WPTextBufferFormat, 1);
2089 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2090 gtk_widget_grab_focus (priv->msg_body);
2091 buffer_format->bold = (format_state->bold != FALSE);
2092 buffer_format->italic = (format_state->italics != FALSE);
2093 buffer_format->color = format_state->color;
2094 buffer_format->font_size = format_state->font_size;
2095 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2096 buffer_format->justification = format_state->justification;
2097 buffer_format->bullet = format_state->bullet;
2099 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2101 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2102 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2103 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2104 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2105 buffer_format->cs.font = (buffer_format->font != current_format->font);
2106 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2107 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2109 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2110 if (buffer_format->cs.bold) {
2111 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2112 GINT_TO_POINTER (buffer_format->bold&0x1));
2114 if (buffer_format->cs.italic) {
2115 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2116 GINT_TO_POINTER (buffer_format->italic&0x1));
2118 if (buffer_format->cs.color) {
2119 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2120 GINT_TO_POINTER (&(buffer_format->color)));
2122 if (buffer_format->cs.font_size) {
2123 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2124 GINT_TO_POINTER (buffer_format->font_size));
2126 if (buffer_format->cs.justification) {
2127 switch (buffer_format->justification) {
2128 case GTK_JUSTIFY_LEFT:
2129 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2130 GINT_TO_POINTER(TRUE));
2132 case GTK_JUSTIFY_CENTER:
2133 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2134 GINT_TO_POINTER(TRUE));
2136 case GTK_JUSTIFY_RIGHT:
2137 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2138 GINT_TO_POINTER(TRUE));
2145 if (buffer_format->cs.font) {
2146 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2147 GINT_TO_POINTER (buffer_format->font));
2149 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2150 if (buffer_format->cs.bullet) {
2151 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2152 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2154 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2156 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2158 g_free (buffer_format);
2159 g_free (current_format);
2161 /* Check dimming rules */
2162 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2163 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2167 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2169 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2171 ModestWindowPrivate *parent_priv;
2172 ModestMsgEditWindowPrivate *priv;
2174 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2175 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2177 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2178 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2179 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2180 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2182 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2183 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2184 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2187 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2189 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2190 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2192 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2193 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2195 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2196 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2199 switch (buffer_format->justification)
2201 case GTK_JUSTIFY_LEFT:
2202 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2204 case GTK_JUSTIFY_CENTER:
2205 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2207 case GTK_JUSTIFY_RIGHT:
2208 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2215 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2217 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2218 G_CALLBACK (modest_msg_edit_window_color_button_change),
2220 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2221 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2222 G_CALLBACK (modest_msg_edit_window_color_button_change),
2225 if (priv->current_size_index != buffer_format->font_size) {
2229 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2230 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2234 priv->current_size_index = buffer_format->font_size;
2236 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2237 markup = g_strconcat ("<span font_family='Sans'>",
2238 size_text, "</span>", NULL);
2240 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2244 gtk_tree_path_free (path);
2247 if (priv->current_face_index != buffer_format->font) {
2251 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2252 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2256 priv->current_face_index = buffer_format->font;
2257 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2258 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2259 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2266 g_free (buffer_format);
2272 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2274 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2275 ModestMsgEditWindowPrivate *priv;
2276 GtkWidget *dialog = NULL;
2278 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2279 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2281 dialog = hildon_color_chooser_new ();
2282 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2283 g_free (buffer_format);
2285 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2287 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2288 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2291 gtk_widget_destroy (dialog);
2296 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2298 ModestMsgEditWindowPrivate *priv;
2299 GtkWidget *dialog = NULL;
2300 GdkColor *old_color = NULL;
2302 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2303 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2305 dialog = hildon_color_chooser_new ();
2306 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2308 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2310 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2311 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2313 gtk_widget_destroy (dialog);
2318 create_stream_for_uri (const gchar* uri)
2323 TnyStream *result = NULL;
2325 GnomeVFSHandle *handle = NULL;
2326 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2327 if (test == GNOME_VFS_OK) {
2328 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2329 /* Streams over OBEX (Bluetooth) are not seekable but
2330 * we expect them to be (we might need to read them
2331 * several times). So if this is a Bluetooth URI just
2332 * read the whole file into memory (this is not a fast
2333 * protocol so we can assume that these files are not
2334 * going to be very big) */
2335 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2336 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2337 TnyStream *memstream = tny_camel_mem_stream_new ();
2338 tny_stream_write_to_stream (vfssstream, memstream);
2339 g_object_unref (vfssstream);
2342 result = vfssstream;
2350 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2353 ModestMsgEditWindowPrivate *priv;
2354 GtkWidget *dialog = NULL;
2356 GSList *uris = NULL;
2357 GSList *uri_node = NULL;
2359 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2361 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2362 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2363 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2365 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2367 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2368 GTK_WINDOW (dialog), GTK_WINDOW (window));
2370 response = gtk_dialog_run (GTK_DIALOG (dialog));
2372 case GTK_RESPONSE_OK:
2374 gchar *current_folder;
2375 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2376 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2377 if (current_folder && current_folder != '\0') {
2379 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2380 current_folder, &err);
2382 g_debug ("Error storing latest used folder: %s", err->message);
2386 g_free (current_folder);
2392 gtk_widget_destroy (dialog);
2394 g_object_ref (window);
2395 /* The operation could take some time so allow the dialog to be closed */
2396 while (gtk_events_pending ())
2397 gtk_main_iteration ();
2399 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2401 GnomeVFSHandle *handle = NULL;
2402 GnomeVFSResult result;
2403 GtkTextIter position;
2404 GtkTextMark *insert_mark;
2406 uri = (const gchar *) uri_node->data;
2407 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2408 if (result == GNOME_VFS_OK) {
2410 GnomeVFSFileInfo *info;
2411 gchar *filename, *basename, *escaped_filename;
2412 TnyMimePart *mime_part;
2414 const gchar *mime_type = NULL;
2415 GnomeVFSURI *vfs_uri;
2416 guint64 stream_size;
2418 gnome_vfs_close (handle);
2419 vfs_uri = gnome_vfs_uri_new (uri);
2421 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2422 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2423 g_free (escaped_filename);
2424 gnome_vfs_uri_unref (vfs_uri);
2425 info = gnome_vfs_file_info_new ();
2427 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2428 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2430 mime_type = gnome_vfs_file_info_get_mime_type (info);
2432 mime_part = tny_platform_factory_new_mime_part
2433 (modest_runtime_get_platform_factory ());
2435 TnyStream *stream = create_stream_for_uri (uri);
2437 if (stream == NULL) {
2439 modest_platform_information_banner (NULL, NULL,
2440 _FM("sfil_ib_opening_not_allowed"));
2442 g_object_unref (mime_part);
2443 gnome_vfs_file_info_unref (info);
2447 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2449 content_id = g_strdup_printf ("%d", priv->next_cid);
2450 tny_mime_part_set_content_id (mime_part, content_id);
2451 g_free (content_id);
2454 basename = g_path_get_basename (filename);
2455 tny_mime_part_set_filename (mime_part, basename);
2458 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2460 if (pixbuf != NULL) {
2461 priv->images_size += stream_size;
2462 priv->images_count ++;
2463 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2464 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2465 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2466 tny_mime_part_get_content_id (mime_part), pixbuf);
2467 g_object_unref (pixbuf);
2469 tny_list_prepend (priv->images, (GObject *) mime_part);
2470 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2472 modest_platform_information_banner (NULL, NULL,
2473 _("mail_ib_file_operation_failed"));
2477 g_object_unref (mime_part);
2478 gnome_vfs_file_info_unref (info);
2482 g_object_unref (window);
2486 on_attach_file_response (GtkDialog *dialog,
2490 GSList *uris = NULL;
2492 GnomeVFSFileSize total_size, allowed_size;
2493 ModestMsgEditWindow *window;
2494 ModestMsgEditWindowPrivate *priv;
2499 case GTK_RESPONSE_OK:
2501 gchar *current_folder;
2503 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2504 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2505 if (current_folder && current_folder != '\0') {
2507 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2508 current_folder, &err);
2510 g_debug ("Error storing latest used folder: %s", err->message);
2514 g_free (current_folder);
2521 window = MODEST_MSG_EDIT_WINDOW (user_data);
2522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2524 /* allowed size is the maximum size - what's already there */
2525 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2526 &att_num, &att_size);
2527 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2530 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2532 const gchar *uri = (const gchar *) uri_node->data;
2535 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2537 if (total_size > allowed_size) {
2538 g_debug ("%s: total size: %u",
2539 __FUNCTION__, (unsigned int)total_size);
2542 allowed_size -= total_size;
2544 g_slist_foreach (uris, (GFunc) g_free, NULL);
2545 g_slist_free (uris);
2547 gtk_widget_destroy (GTK_WIDGET (dialog));
2551 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2553 GtkWidget *dialog = NULL;
2554 ModestMsgEditWindowPrivate *priv;
2557 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2561 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2564 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2565 GTK_FILE_CHOOSER_ACTION_OPEN);
2566 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2567 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2568 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2569 if (conf_folder && conf_folder[0] != '\0') {
2570 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2573 /* Set the default folder to documents folder */
2574 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2577 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2578 ".documents", NULL);
2580 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2581 g_free (docs_folder);
2583 g_free (conf_folder);
2584 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2585 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2586 GTK_WINDOW (dialog), GTK_WINDOW (window));
2588 /* Connect to response & show */
2589 g_signal_connect (dialog, "response",
2590 G_CALLBACK (on_attach_file_response), window);
2591 gtk_widget_show (dialog);
2596 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2598 GnomeVFSFileSize allowed_size)
2601 GnomeVFSHandle *handle = NULL;
2602 ModestMsgEditWindowPrivate *priv;
2603 GnomeVFSResult result;
2604 GnomeVFSFileSize size = 0;
2605 g_return_val_if_fail (window, 0);
2606 g_return_val_if_fail (uri, 0);
2608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2610 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2611 if (result == GNOME_VFS_OK) {
2612 TnyMimePart *mime_part;
2614 const gchar *mime_type = NULL;
2616 gchar *escaped_filename;
2619 GnomeVFSFileInfo *info;
2620 GnomeVFSURI *vfs_uri;
2622 gnome_vfs_close (handle);
2623 vfs_uri = gnome_vfs_uri_new (uri);
2626 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2627 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2628 g_free (escaped_filename);
2629 gnome_vfs_uri_unref (vfs_uri);
2631 info = gnome_vfs_file_info_new ();
2633 if (gnome_vfs_get_file_info (uri,
2635 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2637 mime_type = gnome_vfs_file_info_get_mime_type (info);
2638 mime_part = tny_platform_factory_new_mime_part
2639 (modest_runtime_get_platform_factory ());
2641 /* try to get the attachment's size; this may fail for weird
2642 * file systems, like obex, upnp... */
2643 if (allowed_size != 0 &&
2644 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2646 if (size > allowed_size) {
2647 modest_platform_information_banner (NULL, NULL,
2648 _("mail_ib_error_attachment_size"));
2653 g_debug ("%s: could not get attachment size", __FUNCTION__);
2655 stream = create_stream_for_uri (uri);
2657 if (stream == NULL) {
2659 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2661 g_object_unref (mime_part);
2663 gnome_vfs_file_info_unref (info);
2667 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2668 g_object_unref (stream);
2670 content_id = g_strdup_printf ("%d", priv->next_cid);
2671 tny_mime_part_set_content_id (mime_part, content_id);
2672 g_free (content_id);
2675 basename = g_path_get_basename (filename);
2676 tny_mime_part_set_filename (mime_part, basename);
2679 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2680 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2682 info->size == 0, info->size);
2683 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2684 gtk_widget_show_all (priv->attachments_caption);
2685 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2687 g_object_unref (mime_part);
2688 gnome_vfs_file_info_unref (info);
2695 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2698 ModestMsgEditWindowPrivate *priv;
2701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2702 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2704 if (att_list == NULL) {
2705 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2706 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2707 g_object_unref (att_list);
2711 g_object_ref (att_list);
2714 if (tny_list_get_length (att_list) == 0) {
2715 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2717 gboolean dialog_response;
2718 gchar *message = NULL;
2719 gchar *filename = NULL;
2721 if (tny_list_get_length (att_list) == 1) {
2723 iter = tny_list_create_iterator (att_list);
2724 part = (TnyMimePart *) tny_iterator_get_current (iter);
2725 g_object_unref (iter);
2726 if (TNY_IS_MSG (part)) {
2727 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2729 filename = tny_header_dup_subject (header);
2730 g_object_unref (header);
2732 if (filename == NULL) {
2733 filename = g_strdup (_("mail_va_no_subject"));
2736 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2738 g_object_unref (part);
2740 filename = g_strdup ("");
2742 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2743 "emev_nc_delete_attachments",
2744 tny_list_get_length (att_list)), filename);
2747 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2751 if (dialog_response != GTK_RESPONSE_OK) {
2752 g_object_unref (att_list);
2756 for (iter = tny_list_create_iterator (att_list);
2757 !tny_iterator_is_done (iter);
2758 tny_iterator_next (iter)) {
2759 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2760 const gchar *att_id;
2761 tny_list_remove (priv->attachments, (GObject *) mime_part);
2763 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2765 if (tny_list_get_length (priv->attachments) == 0)
2766 gtk_widget_hide (priv->attachments_caption);
2767 att_id = tny_mime_part_get_content_id (mime_part);
2769 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2771 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2772 g_object_unref (mime_part);
2774 g_object_unref (iter);
2777 g_object_unref (att_list);
2779 /* if the last attachment has been removed, focus the Subject: field */
2780 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2781 gtk_widget_grab_focus (priv->subject_field);
2785 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2788 ModestMsgEditWindowPrivate *priv;
2791 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2793 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &new_color);
2795 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2797 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2801 font_size_clicked (GtkToolButton *button,
2802 ModestMsgEditWindow *window)
2804 ModestMsgEditWindowPrivate *priv;
2805 GtkWidget *selector, *dialog;
2807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2809 selector = hildon_touch_selector_new ();
2810 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2811 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2813 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2814 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2815 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2817 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2821 WPTextBufferFormat format;
2823 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2825 memset (&format, 0, sizeof (format));
2826 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2828 format.cs.font_size = TRUE;
2829 format.cs.text_position = TRUE;
2830 format.cs.font = TRUE;
2831 format.font_size = new_index;
2832 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2834 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2835 GINT_TO_POINTER (new_index)))
2836 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2838 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2839 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2840 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2841 size_text, "</span>", NULL);
2843 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2847 gtk_widget_destroy (dialog);
2849 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2854 font_face_clicked (GtkToolButton *button,
2855 ModestMsgEditWindow *window)
2857 ModestMsgEditWindowPrivate *priv;
2858 GtkWidget *selector, *dialog;
2859 GtkCellRenderer *renderer;
2861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2863 selector = hildon_touch_selector_new ();
2864 renderer = gtk_cell_renderer_text_new ();
2865 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2866 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2867 renderer, "family", 0, "text", 0, NULL);
2868 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2870 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2871 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2872 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2874 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2875 gint new_font_index;
2879 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2880 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2881 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2885 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2887 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2888 GINT_TO_POINTER(new_font_index)))
2889 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2891 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2892 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2894 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2898 gtk_tree_path_free (path);
2901 gtk_widget_destroy (dialog);
2903 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2908 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2911 ModestMsgEditWindowPrivate *priv = NULL;
2912 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2914 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2915 if (!priv->update_caption_visibility)
2918 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2920 gtk_widget_show (priv->cc_caption);
2922 gtk_widget_hide (priv->cc_caption);
2924 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2928 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2931 ModestMsgEditWindowPrivate *priv = NULL;
2932 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2935 if (!priv->update_caption_visibility)
2938 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2940 gtk_widget_show (priv->bcc_caption);
2942 gtk_widget_hide (priv->bcc_caption);
2944 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2948 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2949 ModestRecptEditor *editor)
2951 ModestMsgEditWindowPrivate *priv;
2953 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2954 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2956 /* we check for low-mem; in that case, show a warning, and don't allow
2957 * for the addressbook
2959 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2962 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964 if (editor == NULL) {
2965 GtkWidget *view_focus, *parent;
2966 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2968 /* This code should be kept in sync with ModestRecptEditor. The
2969 textview inside the recpt editor is the one that really gets the
2970 focus. As it's inside a scrolled window, and this one inside the
2971 hbox recpt editor inherits from, we'll need to go up in the
2972 hierarchy to know if the text view is part of the recpt editor
2973 or if it's a different text entry */
2974 parent = gtk_widget_get_parent (view_focus);
2975 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2976 editor = MODEST_RECPT_EDITOR (parent);
2979 editor = MODEST_RECPT_EDITOR (priv->to_field);
2982 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2986 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2988 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2990 modest_msg_edit_window_open_addressbook (window, NULL);
2994 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2995 gboolean show_toolbar)
2997 ModestWindowPrivate *parent_priv;
2998 ModestMsgEditWindowPrivate *priv;
3000 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3002 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3004 /* We can not just use the code of
3005 modest_msg_edit_window_setup_toolbar because it has a
3006 mixture of both initialization and creation code. */
3008 gint current_format;
3009 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3010 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3011 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3012 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3014 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3017 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3019 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3020 if (hildon_check_button_get_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button)) != show_toolbar) {
3021 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button), show_toolbar);
3026 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3027 TnyHeaderFlags priority_flags)
3029 ModestMsgEditWindowPrivate *priv;
3030 ModestWindowPrivate *parent_priv;
3032 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3037 if (priv->priority_flags != priority_flags) {
3038 GtkAction *priority_action = NULL;
3040 priv->priority_flags = priority_flags;
3042 switch (priority_flags) {
3043 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3044 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3045 MODEST_HEADER_ICON_HIGH,
3046 HILDON_ICON_SIZE_SMALL);
3047 gtk_widget_show (priv->priority_icon);
3048 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3049 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3051 case TNY_HEADER_FLAG_LOW_PRIORITY:
3052 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3053 MODEST_HEADER_ICON_LOW,
3054 HILDON_ICON_SIZE_SMALL);
3055 gtk_widget_show (priv->priority_icon);
3056 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3057 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3060 gtk_widget_hide (priv->priority_icon);
3061 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3062 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3065 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3066 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3068 gtk_widget_queue_resize (priv->subject_box);
3072 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3075 ModestMsgEditWindowPrivate *priv;
3076 ModestWindowPrivate *parent_priv;
3077 gint current_format;
3079 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3081 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3084 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3085 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3087 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3089 if (current_format != file_format) {
3090 switch (file_format) {
3091 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3092 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3093 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3094 update_signature (window, priv->last_from_account, priv->last_from_account);
3095 if (parent_priv->toolbar)
3096 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3097 MODEST_MSG_EDIT_WINDOW (window));
3099 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3103 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3104 response = gtk_dialog_run (GTK_DIALOG (dialog));
3105 gtk_widget_destroy (dialog);
3106 if (response == GTK_RESPONSE_OK) {
3107 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3108 if (parent_priv->toolbar)
3109 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3110 MODEST_MSG_EDIT_WINDOW (window));
3112 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3113 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3118 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3119 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3120 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3125 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3128 ModestMsgEditWindowPrivate *priv;
3129 WPTextBufferFormat oldfmt, fmt;
3130 gint old_position = 0;
3134 GdkColor *color = NULL;
3135 gboolean bold, bold_set, italic, italic_set;
3136 gboolean underline, underline_set;
3137 gboolean strikethrough, strikethrough_set;
3138 gboolean position_set;
3139 gboolean font_size_set, font_set, color_set;
3142 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3143 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3145 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3146 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3147 GTK_WINDOW(dialog), GTK_WINDOW (window));
3149 /* First we get the currently selected font information */
3150 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3152 switch (oldfmt.text_position) {
3153 case TEXT_POSITION_NORMAL:
3156 case TEXT_POSITION_SUPERSCRIPT:
3164 g_object_set (G_OBJECT (dialog),
3165 "bold", oldfmt.bold != FALSE,
3166 "bold-set", !oldfmt.cs.bold,
3167 "underline", oldfmt.underline != FALSE,
3168 "underline-set", !oldfmt.cs.underline,
3169 "italic", oldfmt.italic != FALSE,
3170 "italic-set", !oldfmt.cs.italic,
3171 "strikethrough", oldfmt.strikethrough != FALSE,
3172 "strikethrough-set", !oldfmt.cs.strikethrough,
3173 "color", &oldfmt.color,
3174 "color-set", !oldfmt.cs.color,
3175 "size", wp_font_size[oldfmt.font_size],
3176 "size-set", !oldfmt.cs.font_size,
3177 "position", old_position,
3178 "position-set", !oldfmt.cs.text_position,
3179 "family", wp_get_font_name (oldfmt.font),
3180 "family-set", !oldfmt.cs.font,
3183 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3184 GTK_WINDOW (dialog), GTK_WINDOW (window));
3185 gtk_widget_show_all (dialog);
3186 priv->font_dialog = dialog;
3187 response = gtk_dialog_run (GTK_DIALOG (dialog));
3188 priv->font_dialog = NULL;
3189 if (response == GTK_RESPONSE_OK) {
3191 g_object_get( dialog,
3193 "bold-set", &bold_set,
3194 "underline", &underline,
3195 "underline-set", &underline_set,
3197 "italic-set", &italic_set,
3198 "strikethrough", &strikethrough,
3199 "strikethrough-set", &strikethrough_set,
3201 "color-set", &color_set,
3203 "size-set", &font_size_set,
3204 "family", &font_name,
3205 "family-set", &font_set,
3206 "position", &position,
3207 "position-set", &position_set,
3212 if (response == GTK_RESPONSE_OK) {
3213 memset(&fmt, 0, sizeof(fmt));
3219 fmt.italic = italic;
3220 fmt.cs.italic = TRUE;
3222 if (underline_set) {
3223 fmt.underline = underline;
3224 fmt.cs.underline = TRUE;
3226 if (strikethrough_set) {
3227 fmt.strikethrough = strikethrough;
3228 fmt.cs.strikethrough = TRUE;
3233 ? TEXT_POSITION_NORMAL
3234 : ( ( position == 1 )
3235 ? TEXT_POSITION_SUPERSCRIPT
3236 : TEXT_POSITION_SUBSCRIPT );
3237 fmt.cs.text_position = TRUE;
3238 fmt.font_size = oldfmt.font_size;
3242 fmt.cs.color = TRUE;
3245 fmt.font = wp_get_font_index(font_name,
3250 if (font_size_set) {
3251 fmt.cs.font_size = TRUE;
3252 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3254 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3255 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3257 gtk_widget_destroy (dialog);
3259 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3263 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3265 ModestMsgEditWindowPrivate *priv;
3266 ModestWindowPrivate *parent_priv;
3267 gboolean was_rich_text, is_rich_text;
3269 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3270 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3271 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3273 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3275 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3277 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3279 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3280 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3281 MODEST_MSG_EDIT_WINDOW (window));
3284 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3285 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3289 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3291 ModestMsgEditWindowPrivate *priv;
3293 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3294 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3296 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3298 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3299 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3304 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3306 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3308 priv->can_undo = can_undo;
3312 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3314 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3316 priv->can_redo = can_redo;
3320 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3322 ModestMsgEditWindowPrivate *priv;
3323 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3326 return priv->can_undo;
3330 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3332 ModestMsgEditWindowPrivate *priv;
3333 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3334 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3336 return priv->can_redo;
3341 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3344 GtkTextIter match_start, match_end;
3346 if (image_id == NULL)
3349 gtk_text_buffer_get_start_iter (buffer, &iter);
3351 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3352 GSList *tags = gtk_text_iter_get_tags (&match_start);
3354 for (node = tags; node != NULL; node = g_slist_next (node)) {
3355 GtkTextTag *tag = (GtkTextTag *) node->data;
3356 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3357 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3358 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3360 offset = gtk_text_iter_get_offset (&match_start);
3361 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3362 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3366 gtk_text_iter_forward_char (&iter);
3371 message_is_empty (ModestMsgEditWindow *window)
3373 ModestMsgEditWindowPrivate *priv = NULL;
3375 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3376 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3378 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3379 * so we can ignore markup.
3381 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3384 count = gtk_text_buffer_get_char_count (buf);
3390 msg_body_focus (GtkWidget *focus,
3391 GdkEventFocus *event,
3395 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3396 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3397 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3402 recpt_field_changed (GtkTextBuffer *buffer,
3403 ModestMsgEditWindow *editor)
3405 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3406 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3410 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3412 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3413 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3417 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3420 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3421 GtkTextBuffer *buffer;
3423 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3424 gtk_text_buffer_set_modified (buffer, modified);
3425 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3426 gtk_text_buffer_set_modified (buffer, modified);
3427 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3428 gtk_text_buffer_set_modified (buffer, modified);
3429 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3433 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3435 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3436 const char *account_name;
3437 GtkTextBuffer *buffer;
3439 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3440 if (gtk_text_buffer_get_modified (buffer))
3442 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3443 if (gtk_text_buffer_get_modified (buffer))
3445 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3446 if (gtk_text_buffer_get_modified (buffer))
3448 if (gtk_text_buffer_get_modified (priv->text_buffer))
3451 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3452 if (priv->original_mailbox) {
3453 if (!account_name || strcmp (account_name, priv->original_mailbox))
3455 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3466 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3468 ModestMsgEditWindowPrivate *priv = NULL;
3469 GSList *address_list = NULL;
3470 gboolean no_to, no_cc, no_bcc;
3472 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3475 /* check if there's no recipient added */
3476 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3477 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3478 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3481 if (no_to && no_cc && no_bcc) {
3482 /* no recipient contents, then select contacts */
3483 modest_msg_edit_window_open_addressbook (window, NULL);
3488 g_object_ref (window);
3489 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3490 (add_to_addressbook) ? &address_list : NULL)) {
3491 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3492 g_object_unref (window);
3495 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3496 (add_to_addressbook) ? &address_list : NULL)) {
3497 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3498 g_object_unref (window);
3501 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3502 (add_to_addressbook) ? &address_list : NULL)) {
3503 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3504 g_object_unref (window);
3508 /* Add contacts to address book */
3509 if (add_to_addressbook && address_list)
3510 modest_address_book_add_address_list (address_list);
3512 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3513 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3514 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3515 g_object_unref (window);
3522 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3524 GSList *recipients = NULL;
3525 ModestMsgEditWindowPrivate *priv;
3526 gchar *joined, *after_remove, *to, *cc, *bcc;
3528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3530 /* First of all check names */
3531 if (!modest_msg_edit_window_check_names (self, FALSE))
3534 if (!modest_msg_edit_window_has_pending_addresses (self))
3537 /* Don't add the from obviously */
3538 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3539 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3540 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3542 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3547 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3550 recipients = modest_text_utils_split_addresses_list (after_remove);
3551 g_free (after_remove);
3554 /* Offer the user to add recipients to the address book */
3555 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3556 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3561 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3562 ModestMsgEditWindow *window)
3564 modest_msg_edit_window_offer_attach_file (window);
3568 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3570 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3572 return priv->clipboard_text;
3576 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3578 ModestMsgEditWindow *window)
3580 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3581 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3584 /* It could happen that the window was already closed */
3585 if (!GTK_WIDGET_VISIBLE (window))
3588 g_object_ref (window);
3589 text = gtk_clipboard_wait_for_text (selection_clipboard);
3591 if (priv->clipboard_text != NULL) {
3592 g_free (priv->clipboard_text);
3594 priv->clipboard_text = text;
3596 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3598 g_object_unref (window);
3601 static gboolean clipboard_owner_change_idle (gpointer userdata)
3603 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3604 ModestMsgEditWindowPrivate *priv;
3606 gdk_threads_enter ();
3607 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3610 priv->clipboard_owner_idle = 0;
3611 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3612 gdk_threads_leave ();
3618 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3620 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3621 if (priv->clipboard_owner_idle == 0) {
3622 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3623 clipboard_owner_change_idle,
3624 g_object_ref (window),
3630 subject_field_move_cursor (GtkEntry *entry,
3631 GtkMovementStep step,
3636 /* It could happen that the window was already closed */
3637 if (!GTK_WIDGET_VISIBLE (window))
3640 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3644 update_window_title (ModestMsgEditWindow *window)
3646 ModestMsgEditWindowPrivate *priv = NULL;
3647 const gchar *subject;
3649 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3650 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3651 if (subject == NULL || subject[0] == '\0')
3652 subject = _("mail_va_new_email");
3654 gtk_window_set_title (GTK_WINDOW (window), subject);
3660 body_insert_text (GtkTextBuffer *buffer,
3661 GtkTextIter *location,
3664 ModestMsgEditWindow *window)
3666 GtkTextIter end_iter;
3673 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3675 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3677 offset = gtk_text_iter_get_offset (&end_iter);
3678 line = gtk_text_iter_get_line (&end_iter);
3682 while (text_offset < text + len) {
3683 if (*text_offset == '\n')
3685 if (text_lines + line >= MAX_BODY_LINES) {
3686 len = text_offset - text;
3692 utf8_len = g_utf8_strlen (text, len);
3694 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3695 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3696 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3701 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3703 /* Prevent endless recursion */
3704 result = g_strndup (text, utf8_end - text);
3705 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3706 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3707 (gpointer) result, (gpointer) (utf8_end - text),
3709 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3713 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3714 if (priv->max_chars_banner == NULL) {
3715 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3716 _CS("ckdg_ib_maximum_characters_reached"));
3717 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3723 subject_field_changed (GtkEditable *editable,
3724 ModestMsgEditWindow *window)
3726 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3727 update_window_title (window);
3728 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3729 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3730 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3733 subject_field_insert_text (GtkEditable *editable,
3735 gint new_text_length,
3737 ModestMsgEditWindow *window)
3739 GString *result = g_string_new ("");
3741 gint result_len = 0;
3742 const gchar *entry_text = NULL;
3745 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3746 old_length = g_utf8_strlen (entry_text, -1);
3748 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3749 gunichar c = g_utf8_get_char_validated (current, 8);
3750 /* Invalid unichar, stop */
3756 result = g_string_append_unichar (result, c);
3760 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3761 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3764 /* Prevent endless recursion */
3765 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3766 g_signal_emit_by_name (editable, "insert-text",
3767 (gpointer) result->str, (gpointer) result->len,
3768 (gpointer) position, (gpointer) window);
3769 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3773 if (result_len + old_length > 1000) {
3774 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3775 _CS("ckdg_ib_maximum_characters_reached"));
3777 g_string_free (result, TRUE);
3781 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3784 ModestMsgEditWindowPrivate *priv = NULL;
3786 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3789 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3792 gtk_widget_show_all (priv->find_toolbar);
3793 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3795 gtk_widget_hide_all (priv->find_toolbar);
3796 gtk_widget_grab_focus (priv->msg_body);
3801 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3803 GtkTextIter *match_start,
3804 GtkTextIter *match_end)
3806 GtkTextIter end_iter;
3807 gchar *str_casefold;
3810 gchar *range_casefold;
3813 gboolean result = FALSE;
3820 gtk_text_iter_forward_to_end (&end_iter);
3822 str_casefold = g_utf8_casefold (str, -1);
3823 str_chars_n = strlen (str);
3825 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3826 range_casefold = g_utf8_casefold (range_text, -1);
3827 range_chars_n = strlen (range_casefold);
3829 if (range_chars_n < str_chars_n) {
3830 g_free (str_casefold);
3831 g_free (range_text);
3832 g_free (range_casefold);
3836 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3837 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3838 if (!g_utf8_collate (range_subtext, str_casefold)) {
3839 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3841 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3842 match_start, match_end, NULL)) {
3843 g_debug ("Matched string with collate, but not matched in model");
3845 g_free (found_text);
3847 g_free (range_subtext);
3851 g_free (str_casefold);
3852 g_free (range_text);
3853 g_free (range_casefold);
3860 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3861 ModestMsgEditWindow *window)
3863 gchar *current_search = NULL;
3864 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3866 GtkTextIter selection_start, selection_end;
3867 GtkTextIter match_start, match_end;
3868 gboolean continue_search = FALSE;
3870 if (message_is_empty (window)) {
3871 g_free (priv->last_search);
3872 priv->last_search = NULL;
3873 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3877 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3878 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3879 g_free (current_search);
3880 g_free (priv->last_search);
3881 priv->last_search = NULL;
3882 /* Information banner about empty search */
3883 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3887 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3888 continue_search = TRUE;
3890 g_free (priv->last_search);
3891 priv->last_search = g_strdup (current_search);
3894 if (continue_search) {
3895 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3896 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3897 &match_start, &match_end);
3899 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3901 GtkTextIter buffer_start;
3902 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3903 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3904 &match_start, &match_end);
3906 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3909 /* Mark as selected the string found in search */
3911 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3912 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3913 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3915 g_free (priv->last_search);
3916 priv->last_search = NULL;
3918 g_free (current_search);
3922 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3924 ModestMsgEditWindowPrivate *priv;
3926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3931 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3934 ModestMsgEditWindowPrivate *priv;
3936 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3941 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3942 ModestMsgEditWindow *window)
3944 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3948 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3951 ModestMsgEditWindowPrivate *priv;
3952 TnyHeader *header = NULL;
3954 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3955 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3959 if (priv->draft_msg != NULL) {
3960 g_object_unref (priv->draft_msg);
3963 if (draft != NULL) {
3964 g_object_ref (draft);
3965 header = tny_msg_get_header (draft);
3966 if (priv->msg_uid) {
3967 g_free (priv->msg_uid);
3968 priv->msg_uid = NULL;
3970 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3973 priv->draft_msg = draft;
3977 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3978 GtkTextIter *start, GtkTextIter *end,
3981 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3982 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3985 if (tag == NULL) return;
3986 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3987 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3988 replace_with_images (window, priv->images);
3993 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3996 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3998 g_return_if_fail (TNY_IS_MIME_PART (part));
3999 tny_list_prepend (priv->attachments, (GObject *) part);
4000 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4001 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4002 gtk_widget_show_all (priv->attachments_caption);
4003 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4007 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4009 ModestMsgEditWindowPrivate *priv;
4011 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4014 return priv->msg_uid;
4018 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4019 ModestMsgEditWindowWidgetType widget_type)
4021 ModestMsgEditWindowPrivate *priv;
4023 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4024 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4026 switch (widget_type) {
4027 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4028 return priv->msg_body;
4030 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4031 return priv->to_field;
4033 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4034 return priv->cc_field;
4036 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4037 return priv->bcc_field;
4039 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4040 return priv->subject_field;
4042 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4043 return priv->attachments_view;
4051 remove_tags (WPTextBuffer *buffer)
4053 GtkTextIter start, end;
4055 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4056 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4058 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4062 on_account_removed (TnyAccountStore *account_store,
4063 TnyAccount *account,
4066 /* Do nothing if it's a store account, because we use the
4067 transport to send the messages */
4068 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4069 const gchar *parent_acc = NULL;
4070 const gchar *our_acc = NULL;
4072 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4073 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4074 /* Close this window if I'm showing a message of the removed account */
4075 if (strcmp (parent_acc, our_acc) == 0)
4076 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4081 update_signature (ModestMsgEditWindow *self,
4082 const gchar *old_account,
4083 const gchar *new_account)
4085 ModestMsgEditWindowPrivate *priv;
4086 gboolean has_old_signature, has_new_signature;
4088 ModestAccountMgr *mgr;
4091 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4093 gtk_text_buffer_begin_user_action (priv->text_buffer);
4095 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4096 mgr = modest_runtime_get_account_mgr ();
4100 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4101 if (has_old_signature) {
4102 GtkTextIter match_start, match_end;
4104 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4105 seems that the search has some problems
4106 with the blank space at the end */
4107 if (gtk_text_iter_forward_search (&iter, "--",
4108 GTK_TEXT_SEARCH_TEXT_ONLY,
4109 &match_start, NULL, NULL)) {
4110 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4111 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4113 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4114 &match_start, &match_end, NULL)) {
4118 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4123 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4124 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4125 if (has_new_signature) {
4128 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4129 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4131 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4133 WPTextBufferFormat *fmt;
4134 GdkColor style_color;
4135 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4136 gdk_color_parse ("grey", &style_color);
4138 fmt = g_new0 (WPTextBufferFormat, 1);
4139 fmt->color = style_color;
4140 fmt->cs.color = 0x1;
4141 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4145 g_free (full_signature);
4147 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4151 gtk_text_buffer_end_user_action (priv->text_buffer);
4154 static void update_branding (ModestMsgEditWindow *self,
4155 const gchar *new_account)
4157 ModestMsgEditWindowPrivate *priv;
4158 ModestAccountMgr *mgr;
4159 const GdkPixbuf *new_icon = NULL;
4160 gchar *new_label = NULL;
4161 gboolean show = FALSE;
4163 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4165 mgr = modest_runtime_get_account_mgr ();
4167 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4169 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4170 gtk_widget_show (priv->brand_icon);
4173 gtk_widget_hide (priv->brand_icon);
4176 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4177 gtk_widget_show (priv->brand_label);
4181 gtk_widget_hide (priv->brand_label);
4185 gtk_widget_show (priv->brand_container);
4187 gtk_widget_hide (priv->brand_container);
4191 from_field_changed (HildonPickerButton *button,
4192 ModestMsgEditWindow *self)
4194 ModestMsgEditWindowPrivate *priv;
4195 gchar *old_account, *new_account;
4197 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4199 old_account = priv->last_from_account;
4200 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4203 g_warning ("%s, could not get the new account", __FUNCTION__);
4207 /* If the From is the same do nothing */
4208 if (old_account && new_account && !strcmp (old_account, new_account))
4211 priv->last_from_account = new_account;
4213 update_signature (self, old_account, new_account);
4214 update_branding (self, new_account);
4218 typedef struct _MessageSettingsHelper {
4219 ModestMsgEditWindow *window;
4220 GSList *priority_group;
4221 GSList *format_group;
4222 GtkToggleButton *current_priority;
4223 GtkToggleButton *current_format;
4224 } MessageSettingsHelper;
4227 on_priority_toggle (GtkToggleButton *button,
4228 MessageSettingsHelper *helper)
4231 ModestMsgEditWindowPrivate *priv;
4233 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4234 if (gtk_toggle_button_get_active (button)) {
4236 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4237 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4238 if ((node_button != button) &&
4239 gtk_toggle_button_get_active (node_button)) {
4240 gtk_toggle_button_set_active (node_button, FALSE);
4243 helper->current_priority = button;
4245 gboolean found = FALSE;
4246 /* If no one is active, activate it again */
4247 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4248 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4249 if (gtk_toggle_button_get_active (node_button)) {
4255 gtk_toggle_button_set_active (button, TRUE);
4261 on_format_toggle (GtkToggleButton *button,
4262 MessageSettingsHelper *helper)
4265 ModestMsgEditWindowPrivate *priv;
4267 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4268 if (gtk_toggle_button_get_active (button)) {
4270 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4271 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4272 if ((node_button != button) &&
4273 gtk_toggle_button_get_active (node_button)) {
4274 gtk_toggle_button_set_active (node_button, FALSE);
4277 helper->current_format = button;
4279 gboolean found = FALSE;
4280 /* If no one is active, activate it again */
4281 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4282 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4283 if (gtk_toggle_button_get_active (node_button)) {
4289 gtk_toggle_button_set_active (button, TRUE);
4296 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4301 GtkWidget *priority_hbox;
4302 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4303 GtkWidget *captioned;
4304 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4305 GtkWidget *format_hbox;
4306 GtkWidget *html_toggle, *text_toggle;
4307 ModestMsgEditWindowPrivate *priv;
4308 MessageSettingsHelper helper = {0,};
4310 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4311 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4312 helper.window = window;
4313 helper.priority_group = NULL;
4314 helper.format_group = NULL;
4316 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4317 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4319 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4320 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4321 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4322 vbox = gtk_vbox_new (FALSE, 0);
4323 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4324 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4325 gtk_container_add (GTK_CONTAINER (align), vbox);
4326 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4327 gtk_widget_show (align);
4328 gtk_widget_show (vbox);
4330 /* Priority toggles */
4331 priority_hbox = gtk_hbox_new (TRUE, 0);
4332 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4333 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4334 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4335 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4336 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4337 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4338 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4339 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4340 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4341 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4342 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4343 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4344 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4345 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4346 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4347 gtk_widget_show_all (priority_hbox);
4348 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4349 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4350 gtk_widget_show (captioned);
4351 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4353 /* format toggles */
4354 format_hbox = gtk_hbox_new (TRUE, 0);
4355 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4356 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4357 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4358 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4359 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4360 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4361 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4362 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4363 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4364 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4365 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4366 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4367 gtk_widget_show_all (format_hbox);
4368 gtk_widget_show (format_hbox);
4369 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4372 g_object_unref (title_sizegroup);
4373 g_object_unref (value_sizegroup);
4375 /* Set current values */
4376 switch (priv->priority_flags) {
4377 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4378 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4379 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4381 case TNY_HEADER_FLAG_LOW_PRIORITY:
4382 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4383 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4386 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4387 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4391 switch (modest_msg_edit_window_get_format (window)) {
4392 case MODEST_MSG_EDIT_FORMAT_TEXT:
4393 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4394 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4396 case MODEST_MSG_EDIT_FORMAT_HTML:
4398 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4399 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4403 /* Signal connects */
4404 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4405 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4406 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4407 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4408 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4410 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4411 GTK_WINDOW (dialog), GTK_WINDOW (window));
4413 /* Save settings if the user clicked on done */
4414 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4415 TnyHeaderFlags flags;
4416 ModestMsgEditFormat old_format, new_format;
4418 /* Set priority flags */
4419 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4420 if (priv->priority_flags != flags)
4421 modest_msg_edit_window_set_priority_flags (window, flags);
4423 /* Set edit format */
4424 old_format = modest_msg_edit_window_get_format (window);
4425 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4426 if (old_format != new_format) {
4427 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4428 modest_msg_edit_window_set_file_format (window, file_format);
4432 gtk_widget_destroy (dialog);
4433 g_slist_free (helper.priority_group);
4437 on_message_settings (GtkAction *action,
4438 ModestMsgEditWindow *window)
4440 modest_msg_edit_window_show_msg_settings_dialog (window);
4444 on_show_toolbar_button_toggled (HildonCheckButton *button,
4445 ModestMsgEditWindow *window)
4447 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4449 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4450 hildon_check_button_get_active (button));
4454 on_cc_button_toggled (HildonCheckButton *button,
4455 ModestMsgEditWindow *window)
4457 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4459 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4460 hildon_check_button_get_active (button));
4464 on_bcc_button_toggled (HildonCheckButton *button,
4465 ModestMsgEditWindow *window)
4467 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4469 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4470 hildon_check_button_get_active (button));
4474 setup_menu (ModestMsgEditWindow *self)
4476 ModestMsgEditWindowPrivate *priv = NULL;
4478 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4482 /* Settings menu buttons */
4483 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4484 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4486 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4487 APP_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4488 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4489 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4490 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4491 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4493 priv->cc_button = hildon_check_button_new (0);
4494 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4495 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4497 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4499 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4500 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4501 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4502 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4504 priv->bcc_button = hildon_check_button_new (0);
4505 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4506 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4508 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4510 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4511 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4512 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4513 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4515 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4516 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4518 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4519 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4520 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4521 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4522 APP_MENU_CALLBACK (on_message_settings),
4524 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4525 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4527 priv->show_toolbar_button = hildon_check_button_new (0);
4528 gtk_button_set_label (GTK_BUTTON (priv->show_toolbar_button), _("mcen_bd_show_toolbar"));
4529 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
4531 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->show_toolbar_button),
4532 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4533 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4534 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4535 gtk_button_set_alignment (GTK_BUTTON (priv->show_toolbar_button), 0.5, 0.5);
4536 gtk_button_set_alignment (GTK_BUTTON (priv->show_toolbar_button), 0.5, 0.5);
4541 emit_open_addressbook (GtkButton *button,
4542 ModestRecptEditor *editor)
4544 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4548 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4549 const gchar *label, GtkWidget *control)
4551 GtkWidget *abook_button;
4554 GtkWidget *label_widget;
4556 box = gtk_hbox_new (FALSE, 0);
4558 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4559 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4561 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4562 label_widget = gtk_label_new (label);
4563 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4564 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4566 gtk_container_add (GTK_CONTAINER (align), abook_button);
4567 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4568 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4569 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4570 if (title_size_group)
4571 gtk_size_group_add_widget (title_size_group, label_widget);
4572 if (value_size_group)
4573 gtk_size_group_add_widget (value_size_group, control);
4575 g_signal_connect (G_OBJECT (abook_button), "clicked",
4576 G_CALLBACK (emit_open_addressbook), control);
4582 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4584 ModestMsgEditWindowPrivate *priv = NULL;
4586 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4588 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4589 priv->max_chars_banner = NULL;
4593 has_pending_addresses (ModestRecptEditor *recpt_editor)
4595 const gchar *recipients = NULL;
4596 GSList *start_indexes = NULL, *end_indexes = NULL;
4597 GSList *current_start, *current_end;
4598 GtkTextBuffer *buffer;
4599 gint offset_delta = 0;
4601 gboolean has_recipients_to_add = FALSE;
4603 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4604 last_length = g_utf8_strlen (recipients, -1);
4605 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4610 current_start = start_indexes;
4611 current_end = end_indexes;
4612 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4614 while (current_start && !has_recipients_to_add) {
4616 gchar *start_ptr, *end_ptr;
4617 gint start_pos, end_pos;
4619 start_pos = (*((gint*) current_start->data)) + offset_delta;
4620 end_pos = (*((gint*) current_end->data)) + offset_delta;
4622 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4623 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4625 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4627 if (modest_text_utils_validate_recipient (address, NULL)) {
4628 if (!modest_address_book_has_address (address)) {
4629 has_recipients_to_add = TRUE;
4632 current_start = g_slist_next (current_start);
4633 current_end = g_slist_next (current_end);
4635 return has_recipients_to_add;
4639 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4641 ModestMsgEditWindowPrivate *priv = NULL;
4643 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4645 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4647 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4648 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4649 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))
4656 modest_msg_edit_window_set_custom_header_pairs (ModestMsgEditWindow *self,
4657 TnyList *header_pairs)
4659 ModestMsgEditWindowPrivate *priv = NULL;
4661 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
4662 g_return_if_fail (TNY_IS_LIST (header_pairs));
4664 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4665 g_object_unref (priv->custom_header_pairs);
4666 priv->custom_header_pairs = tny_list_copy (header_pairs);