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;
275 GtkWidget *cc_caption;
276 GtkWidget *bcc_caption;
277 gboolean update_caption_visibility;
278 GtkWidget *attachments_caption;
280 GtkTextBuffer *text_buffer;
282 GtkWidget *font_size_toolitem;
283 GtkWidget *font_face_toolitem;
284 GtkWidget *font_color_button;
285 GtkWidget *font_color_toolitem;
286 GSList *font_items_group;
287 GtkTreeModel *faces_model;
288 gint current_face_index;
289 GtkWidget *font_tool_button_label;
290 GtkTreeModel *sizes_model;
291 gint current_size_index;
292 GtkWidget *size_tool_button_label;
294 GtkWidget *find_toolbar;
297 GtkWidget *font_dialog;
300 guint correct_scroll_idle;
301 guint scroll_drag_timeout_id;
305 TnyList *attachments;
310 TnyHeaderFlags priority_flags;
312 gboolean can_undo, can_redo;
313 gulong clipboard_change_handler_id;
314 gulong default_clipboard_change_handler_id;
315 gulong account_removed_handler_id;
316 guint clipboard_owner_idle;
317 gchar *clipboard_text;
326 GtkWidget *cc_button;
327 GtkWidget *bcc_button;
328 GtkWidget *show_toolbar_button;
330 GtkWidget *max_chars_banner;
332 GtkWidget *brand_icon;
333 GtkWidget *brand_label;
334 GtkWidget *brand_container;
336 TnyList *custom_header_pairs;
339 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
340 MODEST_TYPE_MSG_EDIT_WINDOW, \
341 ModestMsgEditWindowPrivate))
343 static GtkWindowClass *parent_class = NULL;
345 /* uncomment the following if you have defined any signals */
346 /* static guint signals[LAST_SIGNAL] = {0}; */
349 modest_msg_edit_window_get_type (void)
351 static GType my_type = 0;
353 static const GTypeInfo my_info = {
354 sizeof(ModestMsgEditWindowClass),
355 NULL, /* base init */
356 NULL, /* base finalize */
357 (GClassInitFunc) modest_msg_edit_window_class_init,
358 NULL, /* class finalize */
359 NULL, /* class data */
360 sizeof(ModestMsgEditWindow),
362 (GInstanceInitFunc) modest_msg_edit_window_init,
365 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
366 "ModestMsgEditWindow",
374 save_state (ModestWindow *self)
376 modest_widget_memory_save (modest_runtime_get_conf(),
377 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
382 restore_settings (ModestMsgEditWindow *self)
384 ModestConf *conf = NULL;
386 conf = modest_runtime_get_conf ();
388 /* Dim at start clipboard actions */
389 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
394 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
396 GObjectClass *gobject_class;
397 ModestWindowClass *modest_window_class;
398 gobject_class = (GObjectClass*) klass;
399 modest_window_class = (ModestWindowClass*) klass;
401 parent_class = g_type_class_peek_parent (klass);
402 gobject_class->finalize = modest_msg_edit_window_finalize;
404 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
405 modest_window_class->save_state_func = save_state;
406 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
408 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
412 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
414 ModestMsgEditWindowPrivate *priv;
415 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
417 priv->msg_body = NULL;
418 priv->from_field = NULL;
419 priv->to_field = NULL;
420 priv->cc_field = NULL;
421 priv->bcc_field = NULL;
422 priv->subject_field = NULL;
423 priv->attachments = TNY_LIST (tny_simple_list_new ());
424 priv->images = TNY_LIST (tny_simple_list_new ());
425 priv->images_size = 0;
426 priv->images_count = 0;
429 priv->cc_caption = NULL;
430 priv->bcc_caption = NULL;
431 priv->update_caption_visibility = FALSE;
433 priv->priority_flags = 0;
435 priv->find_toolbar = NULL;
436 priv->last_search = NULL;
438 priv->draft_msg = NULL;
439 priv->outbox_msg = NULL;
440 priv->msg_uid = NULL;
442 priv->can_undo = FALSE;
443 priv->can_redo = FALSE;
444 priv->clipboard_change_handler_id = 0;
445 priv->default_clipboard_change_handler_id = 0;
446 priv->account_removed_handler_id = 0;
447 priv->clipboard_owner_idle = 0;
448 priv->clipboard_text = NULL;
451 priv->scroll_drag_timeout_id = 0;
452 priv->correct_scroll_idle = 0;
453 priv->last_upper = 0.0;
455 priv->font_dialog = NULL;
456 priv->app_menu = NULL;
458 priv->references = NULL;
459 priv->in_reply_to = NULL;
460 priv->max_chars_banner = NULL;
461 priv->custom_header_pairs = TNY_LIST (tny_simple_list_new ());
463 if (!is_wp_text_buffer_started) {
464 is_wp_text_buffer_started = TRUE;
465 wp_text_buffer_library_init ();
470 hildon_program_add_window (hildon_program_get_instance(),
475 multimailbox_get_default_mailbox (const gchar *account_name)
477 gchar *transport_account;
478 gchar *result = NULL;
480 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
482 TNY_ACCOUNT_TYPE_TRANSPORT);
483 if (transport_account) {
485 ModestProtocolRegistry *registry;
487 registry = modest_runtime_get_protocol_registry ();
489 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
490 MODEST_ACCOUNT_PROTO, TRUE);
492 ModestProtocol *protocol =
493 modest_protocol_registry_get_protocol_by_name (registry,
494 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
496 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
497 ModestPairList *pair_list;
499 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
502 ModestPair *pair = (ModestPair *) pair_list->data;
503 result = g_strdup ((const gchar *) pair->first);
504 modest_pair_list_free (pair_list);
515 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
517 static ModestPairList*
518 get_transports (void)
520 GSList *transports = NULL;
522 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
523 GSList *accounts = modest_account_mgr_account_names (account_mgr,
524 TRUE /* only enabled accounts. */);
526 GSList *cursor = accounts;
528 gchar *account_name = cursor->data;
531 gchar *transport_account;
532 gboolean multi_mailbox = FALSE;
533 ModestProtocol *protocol = NULL;
535 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
537 transport_account = modest_account_mgr_get_server_account_name
538 (modest_runtime_get_account_mgr (),
540 TNY_ACCOUNT_TYPE_TRANSPORT);
541 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
542 ModestPairList *pair_list;
543 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
546 transports = g_slist_concat (transports, pair_list);
547 multi_mailbox = TRUE;
552 if (!multi_mailbox) {
553 gchar *from_string = NULL;
555 from_string = modest_account_mgr_get_from_string (account_mgr,
557 if (from_string && account_name) {
558 gchar *name = account_name;
559 ModestPair *pair = modest_pair_new ((gpointer) name,
560 (gpointer) from_string , TRUE);
561 transports = g_slist_prepend (transports, pair);
566 cursor = cursor->next;
568 g_slist_free (accounts); /* only free the accounts, not the elements,
569 * because they are used in the pairlist */
573 static void window_focus (GtkWindow *window,
577 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
581 scroll_drag_timeout (gpointer userdata)
583 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
584 ModestMsgEditWindowPrivate *priv;
586 /* It could happen that the window was already closed */
587 if (!GTK_WIDGET_VISIBLE (win))
590 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
592 correct_scroll_without_drag_check (win, TRUE);
594 priv->scroll_drag_timeout_id = 0;
600 correct_scroll_without_drag_check_idle (gpointer userdata)
602 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
603 ModestMsgEditWindowPrivate *priv;
605 GdkRectangle rectangle;
606 gint offset_min, offset_max;
610 /* It could happen that the window was already closed */
611 if (!GTK_WIDGET_VISIBLE (w))
614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
616 insert = gtk_text_buffer_get_insert (priv->text_buffer);
617 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
619 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
620 offset_min = priv->msg_body->allocation.y + rectangle.y;
621 offset_max = offset_min + rectangle.height;
623 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
624 offset_min = MAX (offset_min - 48, 0);
625 offset_max = MIN (offset_max + 48, vadj->upper);
627 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
629 priv->correct_scroll_idle = 0;
634 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
636 ModestMsgEditWindowPrivate *priv;
638 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
640 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
643 if (priv->correct_scroll_idle > 0) {
647 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
648 (GSourceFunc) correct_scroll_without_drag_check_idle,
654 correct_scroll (ModestMsgEditWindow *w)
656 ModestMsgEditWindowPrivate *priv;
658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
659 if (gtk_grab_get_current () == priv->msg_body) {
660 if (priv->scroll_drag_timeout_id == 0) {
661 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
663 (GSourceFunc) scroll_drag_timeout,
670 correct_scroll_without_drag_check (w, TRUE);
674 text_buffer_end_user_action (GtkTextBuffer *buffer,
675 ModestMsgEditWindow *userdata)
678 correct_scroll (userdata);
682 text_buffer_mark_set (GtkTextBuffer *buffer,
685 ModestMsgEditWindow *userdata)
687 gtk_text_buffer_begin_user_action (buffer);
688 gtk_text_buffer_end_user_action (buffer);
692 cut_clipboard_check (GtkTextView *text_view,
695 GtkTextBuffer *buffer;
697 buffer = gtk_text_view_get_buffer (text_view);
698 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
699 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
704 copy_clipboard_check (GtkTextView *text_view,
707 GtkTextBuffer *buffer;
709 buffer = gtk_text_view_get_buffer (text_view);
710 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
711 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
716 attachment_deleted (ModestAttachmentsView *attachments_view,
719 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
724 body_size_request (GtkWidget *body,
728 /* Make sure the body always get at least 70 pixels */
729 if (req->height < 70)
734 connect_signals (ModestMsgEditWindow *obj)
736 ModestMsgEditWindowPrivate *priv;
738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
740 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
741 G_CALLBACK (text_buffer_refresh_attributes), obj);
742 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
743 G_CALLBACK (text_buffer_can_undo), obj);
744 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
745 G_CALLBACK (text_buffer_can_redo), obj);
746 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
747 G_CALLBACK (body_changed), obj);
748 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
749 G_CALLBACK (body_insert_text), obj);
750 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
751 G_CALLBACK (body_changed), obj);
752 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
753 G_CALLBACK (text_buffer_end_user_action), obj);
754 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
755 G_CALLBACK (text_buffer_mark_set), obj);
756 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
757 G_CALLBACK (text_buffer_apply_tag), obj);
758 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
759 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
760 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
761 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
762 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
763 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
765 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
766 G_CALLBACK (modest_ui_actions_on_send), obj);
768 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
769 G_CALLBACK (from_field_changed), obj);
771 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
772 G_CALLBACK (msg_body_focus), obj);
773 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
774 G_CALLBACK (msg_body_focus), obj);
775 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
776 G_CALLBACK (body_size_request), obj);
777 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
778 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
779 "changed", G_CALLBACK (recpt_field_changed), obj);
780 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
781 "changed", G_CALLBACK (recpt_field_changed), obj);
782 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
783 "changed", G_CALLBACK (recpt_field_changed), obj);
784 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
785 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
786 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
788 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
789 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
791 priv->clipboard_change_handler_id =
792 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
793 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
794 priv->default_clipboard_change_handler_id =
795 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
796 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
798 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
799 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
800 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
804 init_wp_text_view_style ()
806 static gboolean initialized = FALSE;
809 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
815 init_window (ModestMsgEditWindow *obj)
817 GtkWidget *to_caption, *subject_caption;
818 GtkWidget *main_vbox;
819 ModestMsgEditWindowPrivate *priv;
820 GtkActionGroup *action_group;
821 ModestWindowPrivate *parent_priv;
822 GdkPixbuf *window_icon = NULL;
823 GError *error = NULL;
825 GtkSizeGroup *title_size_group;
826 GtkSizeGroup *value_size_group;
827 GtkWidget *window_box;
828 GtkWidget *window_align;
829 #if (GTK_MINOR_VERSION >= 10)
830 GdkAtom deserialize_type;
832 GtkWidget *from_send_hbox;
833 GtkWidget *send_icon;
834 GtkWidget *attachments_label;
835 GtkWidget *branding_box;
837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
838 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
840 parent_priv->ui_manager = gtk_ui_manager_new();
841 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
842 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
844 /* Add common actions */
845 gtk_action_group_add_actions (action_group,
846 modest_msg_edit_action_entries,
847 G_N_ELEMENTS (modest_msg_edit_action_entries),
849 gtk_action_group_add_actions (action_group,
850 hildon2_msg_edit_action_entries,
851 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
853 gtk_action_group_add_toggle_actions (action_group,
854 modest_msg_edit_toggle_action_entries,
855 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
857 gtk_action_group_add_radio_actions (action_group,
858 modest_msg_edit_alignment_radio_action_entries,
859 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
861 G_CALLBACK (modest_ui_actions_on_change_justify),
863 gtk_action_group_add_radio_actions (action_group,
864 modest_msg_edit_priority_action_entries,
865 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
867 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
869 gtk_action_group_add_radio_actions (action_group,
870 modest_msg_edit_file_format_action_entries,
871 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
872 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
873 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
875 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
876 g_object_unref (action_group);
878 /* Load the UI definition */
879 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
882 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
883 g_clear_error (&error);
886 /* Add accelerators */
887 gtk_window_add_accel_group (GTK_WINDOW (obj),
888 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
890 parent_priv->menubar = NULL;
892 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
893 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
895 /* Note: This ModestPairList* must exist for as long as the picker
896 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
897 * so it can't know how to manage its memory. */
898 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
899 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
901 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
902 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
903 _("mail_va_from"), priv->from_field);
904 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
905 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
906 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
908 priv->to_field = modest_recpt_editor_new ();
909 priv->cc_field = modest_recpt_editor_new ();
910 priv->bcc_field = modest_recpt_editor_new ();
911 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
912 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
913 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
914 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
915 priv->priority_icon = gtk_image_new ();
916 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
917 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
918 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
919 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
920 hildon_entry_set_placeholder ((HildonEntry *) priv->subject_field, _("mail_va_no_subject"));
921 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
922 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
923 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
924 priv->attachments_view = modest_attachments_view_new (NULL);
925 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
926 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
928 priv->header_box = gtk_vbox_new (FALSE, 0);
930 to_caption = _create_addressbook_box
931 (title_size_group, value_size_group,
932 _("mail_va_to"), priv->to_field);
933 priv->cc_caption = _create_addressbook_box
934 (title_size_group, value_size_group,
935 _("mail_va_cc"), priv->cc_field);
936 priv->bcc_caption = _create_addressbook_box
937 (title_size_group, value_size_group,
938 _("mail_va_hotfix1"), priv->bcc_field);
939 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
940 _("mail_va_subject"), FALSE, priv->subject_box);
941 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
942 _("mail_va_attachment"),
944 priv->attachments_view,
945 HILDON_SIZE_AUTO_WIDTH |
946 HILDON_SIZE_AUTO_HEIGHT);
947 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
948 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
951 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
952 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
953 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
954 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
956 g_object_unref (title_size_group);
957 g_object_unref (value_size_group);
959 priv->brand_icon = gtk_image_new ();
960 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
961 priv->brand_label = gtk_label_new (NULL);
962 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
963 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
964 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
965 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
967 from_send_hbox = gtk_hbox_new (FALSE, 0);
968 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
969 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
971 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
972 gtk_widget_show (branding_box);
973 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
974 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
976 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
977 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
978 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
979 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
982 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
983 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
984 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
985 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
986 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
987 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
988 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
989 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
991 init_wp_text_view_style ();
993 priv->msg_body = modest_wp_text_view_new ();
996 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
997 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
998 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
999 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1000 #if (GTK_MINOR_VERSION >= 10)
1001 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1002 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1004 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1005 deserialize_type, TRUE);
1007 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1009 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1010 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1012 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1014 priv->pannable = hildon_pannable_area_new ();
1016 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1018 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1019 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1020 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1022 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1023 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1024 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1026 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1027 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1029 window_box = gtk_vbox_new (FALSE, 0);
1030 gtk_container_add (GTK_CONTAINER(obj), window_box);
1032 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1034 /* Set window icon */
1035 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1037 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1038 g_object_unref (window_icon);
1043 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1045 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1047 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1048 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1049 priv->clipboard_change_handler_id))
1050 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1051 priv->clipboard_change_handler_id);
1052 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1053 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1054 priv->default_clipboard_change_handler_id))
1055 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1056 priv->default_clipboard_change_handler_id);
1058 if (priv->account_removed_handler_id &&
1059 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1060 priv->account_removed_handler_id))
1061 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1062 priv->account_removed_handler_id);
1066 modest_msg_edit_window_finalize (GObject *obj)
1068 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1070 g_object_unref (priv->custom_header_pairs);
1072 if (priv->max_chars_banner) {
1073 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1074 priv->max_chars_banner = FALSE;
1077 /* Sanity check: shouldn't be needed, the window mgr should
1078 call this function before */
1079 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1081 if (priv->font_dialog != NULL) {
1082 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1085 if (priv->clipboard_text != NULL) {
1086 g_free (priv->clipboard_text);
1087 priv->clipboard_text = NULL;
1090 if (priv->draft_msg != NULL) {
1091 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1092 if (TNY_IS_HEADER (header)) {
1093 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1094 modest_window_mgr_unregister_header (mgr, header);
1096 g_object_unref (priv->draft_msg);
1097 priv->draft_msg = NULL;
1099 if (priv->outbox_msg != NULL) {
1100 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1101 if (TNY_IS_HEADER (header)) {
1102 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1103 modest_window_mgr_unregister_header (mgr, header);
1105 g_object_unref (priv->outbox_msg);
1106 priv->outbox_msg = NULL;
1108 if (priv->correct_scroll_idle > 0) {
1109 g_source_remove (priv->correct_scroll_idle);
1110 priv->correct_scroll_idle = 0;
1112 if (priv->scroll_drag_timeout_id > 0) {
1113 g_source_remove (priv->scroll_drag_timeout_id);
1114 priv->scroll_drag_timeout_id = 0;
1116 if (priv->clipboard_owner_idle > 0) {
1117 g_source_remove (priv->clipboard_owner_idle);
1118 priv->clipboard_owner_idle = 0;
1120 if (priv->original_account_name)
1121 g_free (priv->original_account_name);
1122 if (priv->original_mailbox)
1123 g_free (priv->original_mailbox);
1124 g_free (priv->msg_uid);
1125 g_free (priv->last_search);
1126 g_free (priv->references);
1127 g_free (priv->in_reply_to);
1128 g_object_unref (priv->attachments);
1129 g_object_unref (priv->images);
1131 /* This had to stay alive for as long as the picker that used it: */
1132 modest_pair_list_free (priv->from_field_protos);
1134 G_OBJECT_CLASS(parent_class)->finalize (obj);
1138 pixbuf_size_prepared (GdkPixbufLoader *loader,
1141 ModestMsgEditWindow *self)
1143 gint new_height, new_width;
1146 new_height = height;
1150 if (width > IMAGE_MAX_WIDTH) {
1151 new_height = height * IMAGE_MAX_WIDTH / width;
1152 new_width = IMAGE_MAX_WIDTH;
1155 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1159 pixbuf_from_stream (TnyStream *stream,
1160 const gchar *mime_type,
1161 guint64 *stream_size,
1162 ModestMsgEditWindow *self)
1164 GdkPixbufLoader *loader;
1167 GError *error = NULL;
1171 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1173 if (loader == NULL) {
1178 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1180 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1182 tny_stream_reset (TNY_STREAM (stream));
1183 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1184 unsigned char read_buffer[128];
1186 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1188 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1191 /* Allow some UI responsiveness */
1192 while (gtk_events_pending ())
1193 gtk_main_iteration ();
1195 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1197 gdk_pixbuf_loader_close (loader, &error);
1200 g_error_free (error);
1201 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1203 g_object_ref (pixbuf);
1204 g_object_unref (loader);
1209 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1210 GdkPixbuf *new_pixbuf;
1212 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1213 gdk_pixbuf_get_width (pixbuf);
1214 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1215 g_object_unref (pixbuf);
1216 pixbuf = new_pixbuf;
1220 *stream_size = size;
1226 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1228 ModestMsgEditWindowPrivate *priv;
1231 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1233 g_object_ref (self);
1234 for (iter = tny_list_create_iterator (attachments);
1235 !tny_iterator_is_done (iter);
1236 tny_iterator_next (iter)) {
1237 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1238 const gchar *cid = tny_mime_part_get_content_id (part);
1239 const gchar *mime_type = tny_mime_part_get_content_type (part);
1240 if ((cid != NULL)&&(mime_type != NULL)) {
1241 guint64 stream_size;
1242 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1243 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1246 g_object_unref (stream);
1248 if (pixbuf != NULL) {
1249 priv->images_count ++;
1250 priv->images_size += stream_size;
1251 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1252 g_object_unref (pixbuf);
1255 g_object_unref (part);
1257 g_object_unref (iter);
1258 g_object_unref (self);
1262 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1264 TnyMimePart *parent = NULL;
1265 const gchar *content_type = NULL;
1266 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1268 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1270 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1271 parent = g_object_ref (msg);
1272 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1273 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1276 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1277 iter = tny_list_create_iterator (parts);
1278 while (!tny_iterator_is_done (iter)) {
1280 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1281 content_type = tny_mime_part_get_content_type (part);
1282 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1286 g_object_unref (part);
1288 tny_iterator_next (iter);
1290 g_object_unref (iter);
1291 g_object_unref (parts);
1294 if (parent != NULL) {
1295 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1298 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1299 iter = tny_list_create_iterator (parts);
1300 while (!tny_iterator_is_done (iter)) {
1302 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1303 content_type = tny_mime_part_get_content_type (part);
1304 if (content_type && g_str_has_prefix (content_type, "image/")) {
1305 tny_list_prepend (priv->images, (GObject *) part);
1307 g_object_unref (part);
1308 tny_iterator_next (iter);
1310 g_object_unref (iter);
1311 g_object_unref (parts);
1312 g_object_unref (parent);
1317 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1320 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1322 for (iter = tny_list_create_iterator (attachments) ;
1323 !tny_iterator_is_done (iter);
1324 tny_iterator_next (iter)) {
1325 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1326 const gchar *cid = tny_mime_part_get_content_id (part);
1328 char *invalid = NULL;
1329 gint int_cid = strtol (cid, &invalid, 10);
1330 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1331 priv->next_cid = int_cid + 1;
1334 g_object_unref (part);
1336 g_object_unref (iter);
1340 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1343 gchar *to, *cc, *bcc, *subject;
1345 ModestMsgEditWindowPrivate *priv;
1346 ModestWindowPrivate *parent_priv;
1348 TnyHeaderFlags priority_flags;
1349 TnyFolder *msg_folder;
1350 gboolean is_html = FALSE;
1351 gboolean field_view_set;
1352 TnyList *orig_header_pairs;
1354 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1355 g_return_if_fail (TNY_IS_MSG (msg));
1357 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1358 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1360 header = tny_msg_get_header (msg);
1361 to = tny_header_dup_to (header);
1362 cc = tny_header_dup_cc (header);
1363 bcc = tny_header_dup_bcc (header);
1364 subject = tny_header_dup_subject (header);
1366 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1367 priority_flags = tny_header_get_priority (header);
1370 gchar *quoted_names = modest_text_utils_quote_names (to);
1371 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1372 g_free (quoted_names);
1375 field_view_set = TRUE;
1377 gchar *quoted_names = modest_text_utils_quote_names (cc);
1378 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1379 g_free (quoted_names);
1380 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1381 gtk_widget_show (priv->cc_caption);
1382 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1383 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1384 gtk_widget_hide (priv->cc_caption);
1385 field_view_set = FALSE;
1387 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1389 field_view_set = TRUE;
1391 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1392 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1393 g_free (quoted_names);
1394 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1395 gtk_widget_show (priv->bcc_caption);
1396 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1397 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1398 gtk_widget_hide (priv->bcc_caption);
1399 field_view_set = FALSE;
1401 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1405 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1406 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1409 update_window_title (self);
1411 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1412 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1414 if ((body == NULL)||(body[0] == '\0')) {
1416 body = modest_text_utils_convert_to_html ("");
1419 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1420 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1423 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1426 /* Add attachments to the view */
1427 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1428 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1429 if (tny_list_get_length (priv->attachments) == 0) {
1430 gtk_widget_hide (priv->attachments_caption);
1432 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1433 gtk_widget_show_all (priv->attachments_caption);
1435 get_related_images (self, msg);
1436 update_next_cid (self, priv->attachments);
1437 update_next_cid (self, priv->images);
1438 replace_with_images (self, priv->images);
1440 if (preserve_is_rich && !is_html) {
1441 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1442 /* Get the default format required from configuration */
1443 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1444 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1447 /* Set the default focus depending on having already a To: field or not */
1448 if ((!to)||(*to == '\0')) {
1449 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1451 gtk_widget_grab_focus (priv->msg_body);
1454 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1456 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1457 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1459 modest_msg_edit_window_set_modified (self, FALSE);
1461 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1462 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1463 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1464 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1466 if (priv->msg_uid) {
1467 g_free (priv->msg_uid);
1468 priv->msg_uid = NULL;
1471 /* we should set a reference to the incoming message if it is a draft */
1472 msg_folder = tny_msg_get_folder (msg);
1474 if (modest_tny_folder_is_local_folder (msg_folder)) {
1475 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1476 if (type == TNY_FOLDER_TYPE_INVALID)
1477 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1479 if (type == TNY_FOLDER_TYPE_DRAFTS)
1480 priv->draft_msg = g_object_ref(msg);
1481 if (type == TNY_FOLDER_TYPE_OUTBOX)
1482 priv->outbox_msg = g_object_ref(msg);
1483 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1485 g_object_unref (msg_folder);
1488 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1489 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1490 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1491 g_object_unref (orig_header_pairs);
1500 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1502 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1503 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1504 GtkWidget *placeholder;
1505 GtkWidget *tool_item;
1510 GtkWidget *sizes_menu;
1511 GtkWidget *fonts_menu;
1517 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1518 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1519 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1520 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1522 /* Font color placeholder */
1523 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1524 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1527 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1528 priv->font_color_button = modest_color_button_new ();
1529 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1530 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1531 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1532 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1533 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1534 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1535 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1536 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1538 G_CALLBACK (modest_msg_edit_window_color_button_change),
1541 /* Font size and face placeholder */
1542 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1543 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1545 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1546 priv->size_tool_button_label = gtk_label_new (NULL);
1547 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1548 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1549 size_text, "</span>", NULL);
1550 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1551 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1553 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1554 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1555 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1556 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1557 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1558 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1559 gtk_widget_set_sensitive (arrow, FALSE);
1560 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1561 sizes_menu = gtk_menu_new ();
1562 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1563 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1566 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1567 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1569 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1573 if (wp_font_size[size_index] == 12)
1574 priv->current_size_index = size_index;
1578 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1579 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1580 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1581 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1582 priv->font_size_toolitem = tool_item;
1585 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1586 priv->font_tool_button_label = gtk_label_new (NULL);
1587 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1588 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1589 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1591 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1592 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1593 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1594 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1595 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1596 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1597 gtk_widget_set_sensitive (arrow, FALSE);
1598 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1599 fonts_menu = gtk_menu_new ();
1600 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1601 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1604 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1606 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1607 0, wp_get_font_name (font_index),
1610 if (font_index == DEFAULT_FONT)
1611 priv->current_face_index = font_index;
1613 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1614 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1615 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1616 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1617 priv->font_face_toolitem = tool_item;
1619 /* Set expand and homogeneous for remaining items */
1620 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1621 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1622 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1623 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1624 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1625 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1626 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1627 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1628 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1630 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1631 will not show the tool items added to the placeholders) */
1632 gtk_widget_show_all (parent_priv->toolbar);
1634 /* Set the no show all *after* showing all items. We do not
1635 want the toolbar to be shown with a show all because it
1636 could go against the gconf setting regarding showing or not
1637 the toolbar of the editor window */
1638 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1644 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1647 ModestWindowPrivate *parent_priv;
1648 ModestMsgEditWindowPrivate *priv;
1649 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1650 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1651 ModestWindowMgr *mgr = NULL;
1653 g_return_val_if_fail (msg, NULL);
1654 g_return_val_if_fail (account_name, NULL);
1656 mgr = modest_runtime_get_window_mgr ();
1658 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1661 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1663 /* Menubar. Update the state of some toggles */
1664 priv->from_field_protos = get_transports ();
1665 priv->original_mailbox = NULL;
1666 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1667 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1668 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1669 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1670 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1671 priv->original_mailbox = g_strdup (mailbox);
1672 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1673 /* We set the first mailbox as the active mailbox */
1674 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1675 if (priv->original_mailbox != NULL)
1676 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1677 (gpointer) priv->original_mailbox);
1679 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1680 (gpointer) account_name);
1682 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1684 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1685 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1686 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1688 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1689 hildon_touch_selector_get_current_text
1690 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1691 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1692 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1695 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1697 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1699 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1700 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1702 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1704 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1705 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1706 /* Add common dimming rules */
1707 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1708 modest_msg_edit_window_toolbar_dimming_entries,
1709 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1710 MODEST_WINDOW (obj));
1711 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1712 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1713 MODEST_WINDOW (obj));
1714 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1715 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1716 MODEST_WINDOW (obj));
1717 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1718 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1719 MODEST_WINDOW (obj));
1720 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1721 G_CALLBACK (modest_ui_dimming_rules_on_send),
1722 MODEST_WINDOW (obj));
1723 /* Insert dimming rules group for this window */
1724 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1725 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1727 /* Setup app menu */
1728 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1730 /* Checks the dimming rules */
1731 g_object_unref (toolbar_rules_group);
1732 g_object_unref (clipboard_rules_group);
1733 gtk_widget_hide (priv->priority_icon);
1734 gtk_widget_queue_resize (priv->subject_box);
1735 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1737 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1739 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1740 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1741 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1742 priv->update_caption_visibility = TRUE;
1744 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1746 /* Track account-removed signal, this window should be closed
1747 in the case we're creating a mail associated to the account
1749 priv->account_removed_handler_id =
1750 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1752 G_CALLBACK(on_account_removed),
1755 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1757 return (ModestWindow*) obj;
1761 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1763 GString **string_buffer = (GString **) user_data;
1765 *string_buffer = g_string_append (*string_buffer, buffer);
1771 * @result: A new string which should be freed with g_free().
1774 get_formatted_data (ModestMsgEditWindow *edit_window)
1776 ModestMsgEditWindowPrivate *priv;
1777 GString *string_buffer = g_string_new ("");
1779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1781 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1783 modest_text_utils_hyperlinkify (string_buffer);
1785 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1787 return g_string_free (string_buffer, FALSE);
1792 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1795 const gchar *account_name;
1796 ModestMsgEditWindowPrivate *priv;
1797 TnyIterator *att_iter;
1798 const gchar *picker_active_id;
1800 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1804 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1805 g_return_val_if_fail (picker_active_id, NULL);
1806 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1808 /* don't free these (except from) */
1809 data = g_slice_new0 (MsgData);
1810 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1811 data->account_name = g_strdup (account_name);
1812 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1813 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1814 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1815 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1816 data->references = g_strdup (priv->references);
1817 data->in_reply_to = g_strdup (priv->in_reply_to);
1818 if (priv->draft_msg) {
1819 data->draft_msg = g_object_ref (priv->draft_msg);
1820 } else if (priv->outbox_msg) {
1821 data->draft_msg = g_object_ref (priv->outbox_msg);
1823 data->draft_msg = NULL;
1826 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1828 gtk_text_buffer_get_bounds (buf, &b, &e);
1829 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1831 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1832 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1834 data->html_body = NULL;
1836 /* deep-copy the data */
1837 att_iter = tny_list_create_iterator (priv->attachments);
1838 data->attachments = NULL;
1839 while (!tny_iterator_is_done (att_iter)) {
1840 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1841 if (!(TNY_IS_MIME_PART(part))) {
1842 g_warning ("strange data in attachment list");
1843 g_object_unref (part);
1844 tny_iterator_next (att_iter);
1847 data->attachments = g_list_append (data->attachments,
1849 tny_iterator_next (att_iter);
1851 g_object_unref (att_iter);
1853 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1854 att_iter = tny_list_create_iterator (priv->images);
1855 data->images = NULL;
1856 while (!tny_iterator_is_done (att_iter)) {
1857 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1859 if (!(TNY_IS_MIME_PART(part))) {
1860 g_warning ("strange data in attachment list");
1861 g_object_unref (part);
1862 tny_iterator_next (att_iter);
1865 cid = tny_mime_part_get_content_id (part);
1867 gchar *image_tag_id;
1868 GtkTextTag *image_tag;
1870 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1871 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1872 g_free (image_tag_id);
1874 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1876 ((gtk_text_iter_has_tag (&iter, image_tag))||
1877 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1878 data->images = g_list_append (data->images,
1879 g_object_ref (part));
1881 g_object_unref (part);
1882 tny_iterator_next (att_iter);
1884 g_object_unref (att_iter);
1886 data->priority_flags = priv->priority_flags;
1887 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
1894 unref_gobject (GObject *obj, gpointer data)
1896 if (!G_IS_OBJECT(obj))
1898 g_object_unref (obj);
1902 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1905 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1913 g_free (data->from);
1914 g_free (data->subject);
1915 g_free (data->plain_body);
1916 g_free (data->html_body);
1917 g_free (data->account_name);
1918 g_free (data->references);
1919 g_free (data->in_reply_to);
1921 g_object_unref (data->custom_header_pairs);
1923 if (data->draft_msg != NULL) {
1924 g_object_unref (data->draft_msg);
1925 data->draft_msg = NULL;
1928 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1929 g_list_free (data->attachments);
1930 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1931 g_list_free (data->images);
1933 g_slice_free (MsgData, data);
1937 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1939 guint64 *parts_size)
1941 ModestMsgEditWindowPrivate *priv;
1943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1945 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1947 /* TODO: add images */
1948 *parts_size += priv->images_size;
1949 *parts_count += priv->images_count;
1954 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1957 ModestMsgEditWindowPrivate *priv = NULL;
1958 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1962 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1964 return MODEST_MSG_EDIT_FORMAT_HTML;
1966 return MODEST_MSG_EDIT_FORMAT_TEXT;
1970 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1971 ModestMsgEditFormat format)
1973 ModestMsgEditWindowPrivate *priv;
1974 ModestWindowPrivate *parent_priv;
1976 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1977 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1978 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1981 case MODEST_MSG_EDIT_FORMAT_HTML:
1982 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1983 update_signature (self, priv->last_from_account, priv->last_from_account);
1984 if (parent_priv->toolbar)
1985 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
1986 MODEST_MSG_EDIT_WINDOW (self));
1988 case MODEST_MSG_EDIT_FORMAT_TEXT:
1989 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1990 if (parent_priv->toolbar)
1991 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
1992 MODEST_MSG_EDIT_WINDOW (self));
1995 g_return_if_reached ();
1999 ModestMsgEditFormatState *
2000 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2002 ModestMsgEditFormatState *format_state = NULL;
2003 ModestMsgEditWindowPrivate *priv;
2004 WPTextBufferFormat *buffer_format;
2006 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2008 buffer_format = g_new0 (WPTextBufferFormat, 1);
2009 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2011 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2013 format_state = g_new0 (ModestMsgEditFormatState, 1);
2014 format_state->bold = buffer_format->bold&0x1;
2015 format_state->italics = buffer_format->italic&0x1;
2016 format_state->bullet = buffer_format->bullet&0x1;
2017 format_state->color = buffer_format->color;
2018 format_state->font_size = buffer_format->font_size;
2019 format_state->font_family = wp_get_font_name (buffer_format->font);
2020 format_state->justification = buffer_format->justification;
2021 g_free (buffer_format);
2023 return format_state;
2028 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2029 const ModestMsgEditFormatState *format_state)
2031 ModestMsgEditWindowPrivate *priv;
2032 WPTextBufferFormat *buffer_format;
2033 WPTextBufferFormat *current_format;
2035 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2036 g_return_if_fail (format_state != NULL);
2038 buffer_format = g_new0 (WPTextBufferFormat, 1);
2039 current_format = g_new0 (WPTextBufferFormat, 1);
2041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2042 gtk_widget_grab_focus (priv->msg_body);
2043 buffer_format->bold = (format_state->bold != FALSE);
2044 buffer_format->italic = (format_state->italics != FALSE);
2045 buffer_format->color = format_state->color;
2046 buffer_format->font_size = format_state->font_size;
2047 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2048 buffer_format->justification = format_state->justification;
2049 buffer_format->bullet = format_state->bullet;
2051 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2053 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2054 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2055 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2056 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2057 buffer_format->cs.font = (buffer_format->font != current_format->font);
2058 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2059 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2061 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2062 if (buffer_format->cs.bold) {
2063 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2064 GINT_TO_POINTER (buffer_format->bold&0x1));
2066 if (buffer_format->cs.italic) {
2067 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2068 GINT_TO_POINTER (buffer_format->italic&0x1));
2070 if (buffer_format->cs.color) {
2071 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2072 GINT_TO_POINTER (&(buffer_format->color)));
2074 if (buffer_format->cs.font_size) {
2075 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2076 GINT_TO_POINTER (buffer_format->font_size));
2078 if (buffer_format->cs.justification) {
2079 switch (buffer_format->justification) {
2080 case GTK_JUSTIFY_LEFT:
2081 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2082 GINT_TO_POINTER(TRUE));
2084 case GTK_JUSTIFY_CENTER:
2085 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2086 GINT_TO_POINTER(TRUE));
2088 case GTK_JUSTIFY_RIGHT:
2089 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2090 GINT_TO_POINTER(TRUE));
2097 if (buffer_format->cs.font) {
2098 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2099 GINT_TO_POINTER (buffer_format->font));
2101 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2102 if (buffer_format->cs.bullet) {
2103 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2104 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2106 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2108 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2110 g_free (buffer_format);
2111 g_free (current_format);
2113 /* Check dimming rules */
2114 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2115 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2119 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2121 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2123 ModestWindowPrivate *parent_priv;
2124 ModestMsgEditWindowPrivate *priv;
2126 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2127 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2129 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2130 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2131 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2132 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2134 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2135 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2136 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2139 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2141 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2142 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2144 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2145 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2147 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2148 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2151 switch (buffer_format->justification)
2153 case GTK_JUSTIFY_LEFT:
2154 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2156 case GTK_JUSTIFY_CENTER:
2157 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2159 case GTK_JUSTIFY_RIGHT:
2160 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2167 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2169 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2170 G_CALLBACK (modest_msg_edit_window_color_button_change),
2172 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2173 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2174 G_CALLBACK (modest_msg_edit_window_color_button_change),
2177 if (priv->current_size_index != buffer_format->font_size) {
2181 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2182 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2186 priv->current_size_index = buffer_format->font_size;
2188 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2189 markup = g_strconcat ("<span font_family='Sans'>",
2190 size_text, "</span>", NULL);
2192 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2196 gtk_tree_path_free (path);
2199 if (priv->current_face_index != buffer_format->font) {
2203 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2204 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2208 priv->current_face_index = buffer_format->font;
2209 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2210 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2211 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2218 g_free (buffer_format);
2224 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2226 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2227 ModestMsgEditWindowPrivate *priv;
2228 GtkWidget *dialog = NULL;
2230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2231 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2233 dialog = hildon_color_chooser_new ();
2234 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2235 g_free (buffer_format);
2237 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2239 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2240 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2243 gtk_widget_destroy (dialog);
2248 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2250 ModestMsgEditWindowPrivate *priv;
2251 GtkWidget *dialog = NULL;
2252 GdkColor *old_color = NULL;
2254 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2255 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2257 dialog = hildon_color_chooser_new ();
2258 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2260 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2262 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2263 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2265 gtk_widget_destroy (dialog);
2270 create_stream_for_uri (const gchar* uri)
2275 TnyStream *result = NULL;
2277 GnomeVFSHandle *handle = NULL;
2278 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2279 if (test == GNOME_VFS_OK) {
2280 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2281 /* Streams over OBEX (Bluetooth) are not seekable but
2282 * we expect them to be (we might need to read them
2283 * several times). So if this is a Bluetooth URI just
2284 * read the whole file into memory (this is not a fast
2285 * protocol so we can assume that these files are not
2286 * going to be very big) */
2287 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2288 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2289 TnyStream *memstream = tny_camel_mem_stream_new ();
2290 tny_stream_write_to_stream (vfssstream, memstream);
2291 g_object_unref (vfssstream);
2294 result = vfssstream;
2302 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2305 ModestMsgEditWindowPrivate *priv;
2306 GtkWidget *dialog = NULL;
2308 GSList *uris = NULL;
2309 GSList *uri_node = NULL;
2311 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2313 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2314 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2315 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2317 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2319 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2320 GTK_WINDOW (dialog), GTK_WINDOW (window));
2322 response = gtk_dialog_run (GTK_DIALOG (dialog));
2324 case GTK_RESPONSE_OK:
2326 gchar *current_folder;
2327 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2328 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2329 if (current_folder && current_folder != '\0') {
2331 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2332 current_folder, &err);
2334 g_debug ("Error storing latest used folder: %s", err->message);
2338 g_free (current_folder);
2344 gtk_widget_destroy (dialog);
2346 g_object_ref (window);
2347 /* The operation could take some time so allow the dialog to be closed */
2348 while (gtk_events_pending ())
2349 gtk_main_iteration ();
2351 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2353 GnomeVFSHandle *handle = NULL;
2354 GnomeVFSResult result;
2355 GtkTextIter position;
2356 GtkTextMark *insert_mark;
2358 uri = (const gchar *) uri_node->data;
2359 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2360 if (result == GNOME_VFS_OK) {
2362 GnomeVFSFileInfo *info;
2363 gchar *filename, *basename, *escaped_filename;
2364 TnyMimePart *mime_part;
2366 const gchar *mime_type = NULL;
2367 GnomeVFSURI *vfs_uri;
2368 guint64 stream_size;
2370 gnome_vfs_close (handle);
2371 vfs_uri = gnome_vfs_uri_new (uri);
2373 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2374 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2375 g_free (escaped_filename);
2376 gnome_vfs_uri_unref (vfs_uri);
2377 info = gnome_vfs_file_info_new ();
2379 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2380 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2382 mime_type = gnome_vfs_file_info_get_mime_type (info);
2384 mime_part = tny_platform_factory_new_mime_part
2385 (modest_runtime_get_platform_factory ());
2387 TnyStream *stream = create_stream_for_uri (uri);
2389 if (stream == NULL) {
2391 modest_platform_information_banner (NULL, NULL,
2392 _FM("sfil_ib_opening_not_allowed"));
2394 g_object_unref (mime_part);
2395 gnome_vfs_file_info_unref (info);
2399 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2401 content_id = g_strdup_printf ("%d", priv->next_cid);
2402 tny_mime_part_set_content_id (mime_part, content_id);
2403 g_free (content_id);
2406 basename = g_path_get_basename (filename);
2407 tny_mime_part_set_filename (mime_part, basename);
2410 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2412 if (pixbuf != NULL) {
2413 priv->images_size += stream_size;
2414 priv->images_count ++;
2415 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2416 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2417 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2418 tny_mime_part_get_content_id (mime_part), pixbuf);
2419 g_object_unref (pixbuf);
2421 tny_list_prepend (priv->images, (GObject *) mime_part);
2422 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2424 modest_platform_information_banner (NULL, NULL,
2425 _("mail_ib_file_operation_failed"));
2429 g_object_unref (mime_part);
2430 gnome_vfs_file_info_unref (info);
2434 g_object_unref (window);
2438 on_attach_file_response (GtkDialog *dialog,
2442 GSList *uris = NULL;
2444 GnomeVFSFileSize total_size, allowed_size;
2445 ModestMsgEditWindow *window;
2446 ModestMsgEditWindowPrivate *priv;
2451 case GTK_RESPONSE_OK:
2453 gchar *current_folder;
2455 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2456 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2457 if (current_folder && current_folder != '\0') {
2459 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2460 current_folder, &err);
2462 g_debug ("Error storing latest used folder: %s", err->message);
2466 g_free (current_folder);
2473 window = MODEST_MSG_EDIT_WINDOW (user_data);
2474 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2476 /* allowed size is the maximum size - what's already there */
2477 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2478 &att_num, &att_size);
2479 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2482 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2484 const gchar *uri = (const gchar *) uri_node->data;
2487 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2489 if (total_size > allowed_size) {
2490 g_debug ("%s: total size: %u",
2491 __FUNCTION__, (unsigned int)total_size);
2494 allowed_size -= total_size;
2496 g_slist_foreach (uris, (GFunc) g_free, NULL);
2497 g_slist_free (uris);
2499 gtk_widget_destroy (GTK_WIDGET (dialog));
2503 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2505 GtkWidget *dialog = NULL;
2506 ModestMsgEditWindowPrivate *priv;
2509 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2513 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2516 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2517 GTK_FILE_CHOOSER_ACTION_OPEN);
2518 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2519 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2520 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2521 if (conf_folder && conf_folder[0] != '\0') {
2522 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2525 /* Set the default folder to documents folder */
2526 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2529 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2530 ".documents", NULL);
2532 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2533 g_free (docs_folder);
2535 g_free (conf_folder);
2536 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2537 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2538 GTK_WINDOW (dialog), GTK_WINDOW (window));
2540 /* Connect to response & show */
2541 g_signal_connect (dialog, "response",
2542 G_CALLBACK (on_attach_file_response), window);
2543 gtk_widget_show (dialog);
2548 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2550 GnomeVFSFileSize allowed_size)
2553 GnomeVFSHandle *handle = NULL;
2554 ModestMsgEditWindowPrivate *priv;
2555 GnomeVFSResult result;
2556 GnomeVFSFileSize size = 0;
2557 g_return_val_if_fail (window, 0);
2558 g_return_val_if_fail (uri, 0);
2560 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2562 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2563 if (result == GNOME_VFS_OK) {
2564 TnyMimePart *mime_part;
2566 const gchar *mime_type = NULL;
2568 gchar *escaped_filename;
2571 GnomeVFSFileInfo *info;
2572 GnomeVFSURI *vfs_uri;
2574 gnome_vfs_close (handle);
2575 vfs_uri = gnome_vfs_uri_new (uri);
2578 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2579 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2580 g_free (escaped_filename);
2581 gnome_vfs_uri_unref (vfs_uri);
2583 info = gnome_vfs_file_info_new ();
2585 if (gnome_vfs_get_file_info (uri,
2587 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2589 mime_type = gnome_vfs_file_info_get_mime_type (info);
2590 mime_part = tny_platform_factory_new_mime_part
2591 (modest_runtime_get_platform_factory ());
2593 /* try to get the attachment's size; this may fail for weird
2594 * file systems, like obex, upnp... */
2595 if (allowed_size != 0 &&
2596 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2598 if (size > allowed_size) {
2599 modest_platform_information_banner (NULL, NULL,
2600 _("mail_ib_error_attachment_size"));
2605 g_debug ("%s: could not get attachment size", __FUNCTION__);
2607 stream = create_stream_for_uri (uri);
2609 if (stream == NULL) {
2611 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2613 g_object_unref (mime_part);
2615 gnome_vfs_file_info_unref (info);
2619 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2620 g_object_unref (stream);
2622 content_id = g_strdup_printf ("%d", priv->next_cid);
2623 tny_mime_part_set_content_id (mime_part, content_id);
2624 g_free (content_id);
2627 basename = g_path_get_basename (filename);
2628 tny_mime_part_set_filename (mime_part, basename);
2631 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2632 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2634 info->size == 0, info->size);
2635 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2636 gtk_widget_show_all (priv->attachments_caption);
2637 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2639 g_object_unref (mime_part);
2640 gnome_vfs_file_info_unref (info);
2647 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2650 ModestMsgEditWindowPrivate *priv;
2653 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2654 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2656 if (att_list == NULL) {
2657 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2658 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2659 g_object_unref (att_list);
2663 g_object_ref (att_list);
2666 if (tny_list_get_length (att_list) == 0) {
2667 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2669 gboolean dialog_response;
2670 gchar *message = NULL;
2671 gchar *filename = NULL;
2673 if (tny_list_get_length (att_list) == 1) {
2675 iter = tny_list_create_iterator (att_list);
2676 part = (TnyMimePart *) tny_iterator_get_current (iter);
2677 g_object_unref (iter);
2678 if (TNY_IS_MSG (part)) {
2679 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2681 filename = tny_header_dup_subject (header);
2682 g_object_unref (header);
2684 if (filename == NULL) {
2685 filename = g_strdup (_("mail_va_no_subject"));
2688 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2690 g_object_unref (part);
2692 filename = g_strdup ("");
2694 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2695 "emev_nc_delete_attachments",
2696 tny_list_get_length (att_list)), filename);
2699 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2703 if (dialog_response != GTK_RESPONSE_OK) {
2704 g_object_unref (att_list);
2708 for (iter = tny_list_create_iterator (att_list);
2709 !tny_iterator_is_done (iter);
2710 tny_iterator_next (iter)) {
2711 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2712 const gchar *att_id;
2713 tny_list_remove (priv->attachments, (GObject *) mime_part);
2715 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2717 if (tny_list_get_length (priv->attachments) == 0)
2718 gtk_widget_hide (priv->attachments_caption);
2719 att_id = tny_mime_part_get_content_id (mime_part);
2721 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2723 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2724 g_object_unref (mime_part);
2726 g_object_unref (iter);
2729 g_object_unref (att_list);
2731 /* if the last attachment has been removed, focus the Subject: field */
2732 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2733 gtk_widget_grab_focus (priv->subject_field);
2737 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2740 ModestMsgEditWindowPrivate *priv;
2743 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2745 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &new_color);
2747 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2749 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2753 font_size_clicked (GtkToolButton *button,
2754 ModestMsgEditWindow *window)
2756 ModestMsgEditWindowPrivate *priv;
2757 GtkWidget *selector, *dialog;
2759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2761 selector = hildon_touch_selector_new ();
2762 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2763 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2765 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2766 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2767 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2769 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2773 WPTextBufferFormat format;
2775 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2777 memset (&format, 0, sizeof (format));
2778 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2780 format.cs.font_size = TRUE;
2781 format.cs.text_position = TRUE;
2782 format.cs.font = TRUE;
2783 format.font_size = new_index;
2784 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2786 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2787 GINT_TO_POINTER (new_index)))
2788 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2790 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2791 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2792 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2793 size_text, "</span>", NULL);
2795 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2799 gtk_widget_destroy (dialog);
2801 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2806 font_face_clicked (GtkToolButton *button,
2807 ModestMsgEditWindow *window)
2809 ModestMsgEditWindowPrivate *priv;
2810 GtkWidget *selector, *dialog;
2811 GtkCellRenderer *renderer;
2813 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2815 selector = hildon_touch_selector_new ();
2816 renderer = gtk_cell_renderer_text_new ();
2817 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2818 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2819 renderer, "family", 0, "text", 0, NULL);
2820 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2822 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2823 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2824 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2826 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2827 gint new_font_index;
2831 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2832 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2833 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2837 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2839 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2840 GINT_TO_POINTER(new_font_index)))
2841 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2843 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2844 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2846 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2850 gtk_tree_path_free (path);
2853 gtk_widget_destroy (dialog);
2855 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2860 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2863 ModestMsgEditWindowPrivate *priv = NULL;
2864 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2867 if (!priv->update_caption_visibility)
2870 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2872 gtk_widget_show (priv->cc_caption);
2874 gtk_widget_hide (priv->cc_caption);
2876 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2880 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2883 ModestMsgEditWindowPrivate *priv = NULL;
2884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2886 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2887 if (!priv->update_caption_visibility)
2890 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2892 gtk_widget_show (priv->bcc_caption);
2894 gtk_widget_hide (priv->bcc_caption);
2896 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2900 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2901 ModestRecptEditor *editor)
2903 ModestMsgEditWindowPrivate *priv;
2905 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2906 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2908 /* we check for low-mem; in that case, show a warning, and don't allow
2909 * for the addressbook
2911 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2914 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2916 if (editor == NULL) {
2917 GtkWidget *view_focus, *parent;
2918 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2920 /* This code should be kept in sync with ModestRecptEditor. The
2921 textview inside the recpt editor is the one that really gets the
2922 focus. As it's inside a scrolled window, and this one inside the
2923 hbox recpt editor inherits from, we'll need to go up in the
2924 hierarchy to know if the text view is part of the recpt editor
2925 or if it's a different text entry */
2926 parent = gtk_widget_get_parent (view_focus);
2927 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2928 editor = MODEST_RECPT_EDITOR (parent);
2931 editor = MODEST_RECPT_EDITOR (priv->to_field);
2934 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2938 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2940 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2942 modest_msg_edit_window_open_addressbook (window, NULL);
2946 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2947 gboolean show_toolbar)
2949 ModestWindowPrivate *parent_priv;
2950 ModestMsgEditWindowPrivate *priv;
2952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2954 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2956 /* We can not just use the code of
2957 modest_msg_edit_window_setup_toolbar because it has a
2958 mixture of both initialization and creation code. */
2960 gint current_format;
2961 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2962 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2963 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2964 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2966 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2969 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2971 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
2972 if (hildon_check_button_get_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button)) != show_toolbar) {
2973 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button), show_toolbar);
2978 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2979 TnyHeaderFlags priority_flags)
2981 ModestMsgEditWindowPrivate *priv;
2982 ModestWindowPrivate *parent_priv;
2984 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2986 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2987 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2989 if (priv->priority_flags != priority_flags) {
2990 GtkAction *priority_action = NULL;
2992 priv->priority_flags = priority_flags;
2994 switch (priority_flags) {
2995 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2996 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2997 MODEST_HEADER_ICON_HIGH,
2998 HILDON_ICON_SIZE_SMALL);
2999 gtk_widget_show (priv->priority_icon);
3000 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3001 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3003 case TNY_HEADER_FLAG_LOW_PRIORITY:
3004 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3005 MODEST_HEADER_ICON_LOW,
3006 HILDON_ICON_SIZE_SMALL);
3007 gtk_widget_show (priv->priority_icon);
3008 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3009 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3012 gtk_widget_hide (priv->priority_icon);
3013 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3014 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3017 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3018 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3020 gtk_widget_queue_resize (priv->subject_box);
3024 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3027 ModestMsgEditWindowPrivate *priv;
3028 ModestWindowPrivate *parent_priv;
3029 gint current_format;
3031 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3033 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3034 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3036 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3037 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3039 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3041 if (current_format != file_format) {
3042 switch (file_format) {
3043 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3044 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3045 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3046 update_signature (window, priv->last_from_account, priv->last_from_account);
3047 if (parent_priv->toolbar)
3048 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3049 MODEST_MSG_EDIT_WINDOW (window));
3051 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3055 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3056 response = gtk_dialog_run (GTK_DIALOG (dialog));
3057 gtk_widget_destroy (dialog);
3058 if (response == GTK_RESPONSE_OK) {
3059 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3060 if (parent_priv->toolbar)
3061 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3062 MODEST_MSG_EDIT_WINDOW (window));
3064 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3065 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3070 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3071 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3072 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3077 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3080 ModestMsgEditWindowPrivate *priv;
3081 WPTextBufferFormat oldfmt, fmt;
3082 gint old_position = 0;
3086 GdkColor *color = NULL;
3087 gboolean bold, bold_set, italic, italic_set;
3088 gboolean underline, underline_set;
3089 gboolean strikethrough, strikethrough_set;
3090 gboolean position_set;
3091 gboolean font_size_set, font_set, color_set;
3094 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3097 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3098 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3099 GTK_WINDOW(dialog), GTK_WINDOW (window));
3101 /* First we get the currently selected font information */
3102 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3104 switch (oldfmt.text_position) {
3105 case TEXT_POSITION_NORMAL:
3108 case TEXT_POSITION_SUPERSCRIPT:
3116 g_object_set (G_OBJECT (dialog),
3117 "bold", oldfmt.bold != FALSE,
3118 "bold-set", !oldfmt.cs.bold,
3119 "underline", oldfmt.underline != FALSE,
3120 "underline-set", !oldfmt.cs.underline,
3121 "italic", oldfmt.italic != FALSE,
3122 "italic-set", !oldfmt.cs.italic,
3123 "strikethrough", oldfmt.strikethrough != FALSE,
3124 "strikethrough-set", !oldfmt.cs.strikethrough,
3125 "color", &oldfmt.color,
3126 "color-set", !oldfmt.cs.color,
3127 "size", wp_font_size[oldfmt.font_size],
3128 "size-set", !oldfmt.cs.font_size,
3129 "position", old_position,
3130 "position-set", !oldfmt.cs.text_position,
3131 "family", wp_get_font_name (oldfmt.font),
3132 "family-set", !oldfmt.cs.font,
3135 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3136 GTK_WINDOW (dialog), GTK_WINDOW (window));
3137 gtk_widget_show_all (dialog);
3138 priv->font_dialog = dialog;
3139 response = gtk_dialog_run (GTK_DIALOG (dialog));
3140 priv->font_dialog = NULL;
3141 if (response == GTK_RESPONSE_OK) {
3143 g_object_get( dialog,
3145 "bold-set", &bold_set,
3146 "underline", &underline,
3147 "underline-set", &underline_set,
3149 "italic-set", &italic_set,
3150 "strikethrough", &strikethrough,
3151 "strikethrough-set", &strikethrough_set,
3153 "color-set", &color_set,
3155 "size-set", &font_size_set,
3156 "family", &font_name,
3157 "family-set", &font_set,
3158 "position", &position,
3159 "position-set", &position_set,
3164 if (response == GTK_RESPONSE_OK) {
3165 memset(&fmt, 0, sizeof(fmt));
3171 fmt.italic = italic;
3172 fmt.cs.italic = TRUE;
3174 if (underline_set) {
3175 fmt.underline = underline;
3176 fmt.cs.underline = TRUE;
3178 if (strikethrough_set) {
3179 fmt.strikethrough = strikethrough;
3180 fmt.cs.strikethrough = TRUE;
3185 ? TEXT_POSITION_NORMAL
3186 : ( ( position == 1 )
3187 ? TEXT_POSITION_SUPERSCRIPT
3188 : TEXT_POSITION_SUBSCRIPT );
3189 fmt.cs.text_position = TRUE;
3190 fmt.font_size = oldfmt.font_size;
3194 fmt.cs.color = TRUE;
3197 fmt.font = wp_get_font_index(font_name,
3202 if (font_size_set) {
3203 fmt.cs.font_size = TRUE;
3204 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3206 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3207 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3209 gtk_widget_destroy (dialog);
3211 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3215 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3217 ModestMsgEditWindowPrivate *priv;
3218 ModestWindowPrivate *parent_priv;
3219 gboolean was_rich_text, is_rich_text;
3221 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3222 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3223 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3225 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3227 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3229 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3231 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3232 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3233 MODEST_MSG_EDIT_WINDOW (window));
3236 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3237 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3241 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3243 ModestMsgEditWindowPrivate *priv;
3245 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3246 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3248 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3250 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3251 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3256 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3258 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3260 priv->can_undo = can_undo;
3264 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3266 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3268 priv->can_redo = can_redo;
3272 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3274 ModestMsgEditWindowPrivate *priv;
3275 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3276 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3278 return priv->can_undo;
3282 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3284 ModestMsgEditWindowPrivate *priv;
3285 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3288 return priv->can_redo;
3293 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3296 GtkTextIter match_start, match_end;
3298 if (image_id == NULL)
3301 gtk_text_buffer_get_start_iter (buffer, &iter);
3303 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3304 GSList *tags = gtk_text_iter_get_tags (&match_start);
3306 for (node = tags; node != NULL; node = g_slist_next (node)) {
3307 GtkTextTag *tag = (GtkTextTag *) node->data;
3308 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3309 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3310 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3312 offset = gtk_text_iter_get_offset (&match_start);
3313 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3314 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3318 gtk_text_iter_forward_char (&iter);
3323 message_is_empty (ModestMsgEditWindow *window)
3325 ModestMsgEditWindowPrivate *priv = NULL;
3327 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3328 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3330 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3331 * so we can ignore markup.
3333 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3336 count = gtk_text_buffer_get_char_count (buf);
3342 msg_body_focus (GtkWidget *focus,
3343 GdkEventFocus *event,
3347 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3348 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3349 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3354 recpt_field_changed (GtkTextBuffer *buffer,
3355 ModestMsgEditWindow *editor)
3357 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3358 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3362 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3364 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3365 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3369 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3372 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3373 GtkTextBuffer *buffer;
3375 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3376 gtk_text_buffer_set_modified (buffer, modified);
3377 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3378 gtk_text_buffer_set_modified (buffer, modified);
3379 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3380 gtk_text_buffer_set_modified (buffer, modified);
3381 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3385 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3387 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3388 const char *account_name;
3389 GtkTextBuffer *buffer;
3391 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3392 if (gtk_text_buffer_get_modified (buffer))
3394 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3395 if (gtk_text_buffer_get_modified (buffer))
3397 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3398 if (gtk_text_buffer_get_modified (buffer))
3400 if (gtk_text_buffer_get_modified (priv->text_buffer))
3403 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3404 if (priv->original_mailbox) {
3405 if (!account_name || strcmp (account_name, priv->original_mailbox))
3407 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3418 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3420 ModestMsgEditWindowPrivate *priv = NULL;
3421 GSList *address_list = NULL;
3422 gboolean no_to, no_cc, no_bcc;
3424 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3425 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3427 /* check if there's no recipient added */
3428 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3429 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3430 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3433 if (no_to && no_cc && no_bcc) {
3434 /* no recipient contents, then select contacts */
3435 modest_msg_edit_window_open_addressbook (window, NULL);
3440 g_object_ref (window);
3441 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3442 (add_to_addressbook) ? &address_list : NULL)) {
3443 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3444 g_object_unref (window);
3447 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3448 (add_to_addressbook) ? &address_list : NULL)) {
3449 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3450 g_object_unref (window);
3453 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3454 (add_to_addressbook) ? &address_list : NULL)) {
3455 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3456 g_object_unref (window);
3460 /* Add contacts to address book */
3461 if (add_to_addressbook && address_list)
3462 modest_address_book_add_address_list (address_list);
3464 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3465 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3466 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3467 g_object_unref (window);
3474 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3476 GSList *recipients = NULL;
3477 ModestMsgEditWindowPrivate *priv;
3478 gchar *joined, *after_remove, *to, *cc, *bcc;
3480 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3482 /* First of all check names */
3483 if (!modest_msg_edit_window_check_names (self, FALSE))
3486 if (!modest_msg_edit_window_has_pending_addresses (self))
3489 /* Don't add the from obviously */
3490 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3491 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3492 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3494 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3499 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3502 recipients = modest_text_utils_split_addresses_list (after_remove);
3503 g_free (after_remove);
3506 /* Offer the user to add recipients to the address book */
3507 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3508 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3513 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3514 ModestMsgEditWindow *window)
3516 modest_msg_edit_window_offer_attach_file (window);
3520 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3522 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3524 return priv->clipboard_text;
3528 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3530 ModestMsgEditWindow *window)
3532 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3533 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3536 /* It could happen that the window was already closed */
3537 if (!GTK_WIDGET_VISIBLE (window))
3540 g_object_ref (window);
3541 text = gtk_clipboard_wait_for_text (selection_clipboard);
3543 if (priv->clipboard_text != NULL) {
3544 g_free (priv->clipboard_text);
3546 priv->clipboard_text = text;
3548 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3550 g_object_unref (window);
3553 static gboolean clipboard_owner_change_idle (gpointer userdata)
3555 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3556 ModestMsgEditWindowPrivate *priv;
3558 gdk_threads_enter ();
3559 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3560 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3562 priv->clipboard_owner_idle = 0;
3563 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3564 gdk_threads_leave ();
3570 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3572 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3573 if (priv->clipboard_owner_idle == 0) {
3574 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3575 clipboard_owner_change_idle,
3576 g_object_ref (window),
3582 subject_field_move_cursor (GtkEntry *entry,
3583 GtkMovementStep step,
3588 /* It could happen that the window was already closed */
3589 if (!GTK_WIDGET_VISIBLE (window))
3592 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3596 update_window_title (ModestMsgEditWindow *window)
3598 ModestMsgEditWindowPrivate *priv = NULL;
3599 const gchar *subject;
3601 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3602 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3603 if (subject == NULL || subject[0] == '\0')
3604 subject = _("mail_va_new_email");
3606 gtk_window_set_title (GTK_WINDOW (window), subject);
3612 body_insert_text (GtkTextBuffer *buffer,
3613 GtkTextIter *location,
3616 ModestMsgEditWindow *window)
3618 GtkTextIter end_iter;
3625 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3627 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3629 offset = gtk_text_iter_get_offset (&end_iter);
3630 line = gtk_text_iter_get_line (&end_iter);
3634 while (text_offset < text + len) {
3635 if (*text_offset == '\n')
3637 if (text_lines + line >= MAX_BODY_LINES) {
3638 len = text_offset - text;
3644 utf8_len = g_utf8_strlen (text, len);
3646 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3647 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3648 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3653 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3655 /* Prevent endless recursion */
3656 result = g_strndup (text, utf8_end - text);
3657 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3658 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3659 (gpointer) result, (gpointer) (utf8_end - text),
3661 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3665 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3666 if (priv->max_chars_banner == NULL) {
3667 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3668 _CS("ckdg_ib_maximum_characters_reached"));
3669 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3675 subject_field_changed (GtkEditable *editable,
3676 ModestMsgEditWindow *window)
3678 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3679 update_window_title (window);
3680 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3681 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3682 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3685 subject_field_insert_text (GtkEditable *editable,
3687 gint new_text_length,
3689 ModestMsgEditWindow *window)
3691 GString *result = g_string_new ("");
3693 gint result_len = 0;
3694 const gchar *entry_text = NULL;
3697 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3698 old_length = g_utf8_strlen (entry_text, -1);
3700 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3701 gunichar c = g_utf8_get_char_validated (current, 8);
3702 /* Invalid unichar, stop */
3708 result = g_string_append_unichar (result, c);
3712 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3713 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3716 /* Prevent endless recursion */
3717 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3718 g_signal_emit_by_name (editable, "insert-text",
3719 (gpointer) result->str, (gpointer) result->len,
3720 (gpointer) position, (gpointer) window);
3721 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3725 if (result_len + old_length > 1000) {
3726 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3727 _CS("ckdg_ib_maximum_characters_reached"));
3729 g_string_free (result, TRUE);
3733 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3736 ModestMsgEditWindowPrivate *priv = NULL;
3738 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3741 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3744 gtk_widget_show_all (priv->find_toolbar);
3745 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3747 gtk_widget_hide_all (priv->find_toolbar);
3748 gtk_widget_grab_focus (priv->msg_body);
3753 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3755 GtkTextIter *match_start,
3756 GtkTextIter *match_end)
3758 GtkTextIter end_iter;
3759 gchar *str_casefold;
3762 gchar *range_casefold;
3765 gboolean result = FALSE;
3772 gtk_text_iter_forward_to_end (&end_iter);
3774 str_casefold = g_utf8_casefold (str, -1);
3775 str_chars_n = strlen (str);
3777 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3778 range_casefold = g_utf8_casefold (range_text, -1);
3779 range_chars_n = strlen (range_casefold);
3781 if (range_chars_n < str_chars_n) {
3782 g_free (str_casefold);
3783 g_free (range_text);
3784 g_free (range_casefold);
3788 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3789 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3790 if (!g_utf8_collate (range_subtext, str_casefold)) {
3791 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3793 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3794 match_start, match_end, NULL)) {
3795 g_debug ("Matched string with collate, but not matched in model");
3797 g_free (found_text);
3799 g_free (range_subtext);
3803 g_free (str_casefold);
3804 g_free (range_text);
3805 g_free (range_casefold);
3812 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3813 ModestMsgEditWindow *window)
3815 gchar *current_search = NULL;
3816 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3818 GtkTextIter selection_start, selection_end;
3819 GtkTextIter match_start, match_end;
3820 gboolean continue_search = FALSE;
3822 if (message_is_empty (window)) {
3823 g_free (priv->last_search);
3824 priv->last_search = NULL;
3825 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3829 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3830 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3831 g_free (current_search);
3832 g_free (priv->last_search);
3833 priv->last_search = NULL;
3834 /* Information banner about empty search */
3835 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3839 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3840 continue_search = TRUE;
3842 g_free (priv->last_search);
3843 priv->last_search = g_strdup (current_search);
3846 if (continue_search) {
3847 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3848 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3849 &match_start, &match_end);
3851 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3853 GtkTextIter buffer_start;
3854 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3855 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3856 &match_start, &match_end);
3858 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3861 /* Mark as selected the string found in search */
3863 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3864 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3865 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3867 g_free (priv->last_search);
3868 priv->last_search = NULL;
3870 g_free (current_search);
3874 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3876 ModestMsgEditWindowPrivate *priv;
3878 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3883 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3886 ModestMsgEditWindowPrivate *priv;
3888 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3893 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3894 ModestMsgEditWindow *window)
3896 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3900 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3903 ModestMsgEditWindowPrivate *priv;
3904 TnyHeader *header = NULL;
3906 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3907 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3911 if (priv->draft_msg != NULL) {
3912 g_object_unref (priv->draft_msg);
3915 if (draft != NULL) {
3916 g_object_ref (draft);
3917 header = tny_msg_get_header (draft);
3918 if (priv->msg_uid) {
3919 g_free (priv->msg_uid);
3920 priv->msg_uid = NULL;
3922 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3925 priv->draft_msg = draft;
3929 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3930 GtkTextIter *start, GtkTextIter *end,
3933 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3934 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3937 if (tag == NULL) return;
3938 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3939 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3940 replace_with_images (window, priv->images);
3945 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3948 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3950 g_return_if_fail (TNY_IS_MIME_PART (part));
3951 tny_list_prepend (priv->attachments, (GObject *) part);
3952 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3953 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3954 gtk_widget_show_all (priv->attachments_caption);
3955 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3959 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3961 ModestMsgEditWindowPrivate *priv;
3963 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3966 return priv->msg_uid;
3970 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3971 ModestMsgEditWindowWidgetType widget_type)
3973 ModestMsgEditWindowPrivate *priv;
3975 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3978 switch (widget_type) {
3979 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3980 return priv->msg_body;
3982 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3983 return priv->to_field;
3985 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3986 return priv->cc_field;
3988 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3989 return priv->bcc_field;
3991 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3992 return priv->subject_field;
3994 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3995 return priv->attachments_view;
4003 remove_tags (WPTextBuffer *buffer)
4005 GtkTextIter start, end;
4007 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4008 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4010 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4014 on_account_removed (TnyAccountStore *account_store,
4015 TnyAccount *account,
4018 /* Do nothing if it's a store account, because we use the
4019 transport to send the messages */
4020 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4021 const gchar *parent_acc = NULL;
4022 const gchar *our_acc = NULL;
4024 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4025 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4026 /* Close this window if I'm showing a message of the removed account */
4027 if (strcmp (parent_acc, our_acc) == 0)
4028 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4033 update_signature (ModestMsgEditWindow *self,
4034 const gchar *old_account,
4035 const gchar *new_account)
4037 ModestMsgEditWindowPrivate *priv;
4038 gboolean has_old_signature, has_new_signature;
4040 ModestAccountMgr *mgr;
4043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4045 gtk_text_buffer_begin_user_action (priv->text_buffer);
4047 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4048 mgr = modest_runtime_get_account_mgr ();
4052 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4053 if (has_old_signature) {
4054 GtkTextIter match_start, match_end;
4056 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4057 seems that the search has some problems
4058 with the blank space at the end */
4059 if (gtk_text_iter_forward_search (&iter, "--",
4060 GTK_TEXT_SEARCH_TEXT_ONLY,
4061 &match_start, NULL, NULL)) {
4062 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4063 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4065 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4066 &match_start, &match_end, NULL)) {
4070 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4075 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4076 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4077 if (has_new_signature) {
4080 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4081 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4083 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4085 WPTextBufferFormat *fmt;
4086 GdkColor style_color;
4087 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4088 gdk_color_parse ("grey", &style_color);
4090 fmt = g_new0 (WPTextBufferFormat, 1);
4091 fmt->color = style_color;
4092 fmt->cs.color = 0x1;
4093 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4097 g_free (full_signature);
4099 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4103 gtk_text_buffer_end_user_action (priv->text_buffer);
4106 static void update_branding (ModestMsgEditWindow *self,
4107 const gchar *new_account)
4109 ModestMsgEditWindowPrivate *priv;
4110 ModestAccountMgr *mgr;
4111 const GdkPixbuf *new_icon = NULL;
4112 gchar *new_label = NULL;
4113 gboolean show = FALSE;
4115 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4117 mgr = modest_runtime_get_account_mgr ();
4119 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4121 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4122 gtk_widget_show (priv->brand_icon);
4125 gtk_widget_hide (priv->brand_icon);
4128 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4129 gtk_widget_show (priv->brand_label);
4133 gtk_widget_hide (priv->brand_label);
4137 gtk_widget_show (priv->brand_container);
4139 gtk_widget_hide (priv->brand_container);
4143 from_field_changed (HildonPickerButton *button,
4144 ModestMsgEditWindow *self)
4146 ModestMsgEditWindowPrivate *priv;
4147 gchar *old_account, *new_account;
4149 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4151 old_account = priv->last_from_account;
4152 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4155 g_warning ("%s, could not get the new account", __FUNCTION__);
4159 /* If the From is the same do nothing */
4160 if (old_account && new_account && !strcmp (old_account, new_account))
4163 priv->last_from_account = new_account;
4165 update_signature (self, old_account, new_account);
4166 update_branding (self, new_account);
4170 typedef struct _MessageSettingsHelper {
4171 ModestMsgEditWindow *window;
4172 GSList *priority_group;
4173 GSList *format_group;
4174 GtkToggleButton *current_priority;
4175 GtkToggleButton *current_format;
4176 } MessageSettingsHelper;
4179 on_priority_toggle (GtkToggleButton *button,
4180 MessageSettingsHelper *helper)
4183 ModestMsgEditWindowPrivate *priv;
4185 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4186 if (gtk_toggle_button_get_active (button)) {
4188 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4189 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4190 if ((node_button != button) &&
4191 gtk_toggle_button_get_active (node_button)) {
4192 gtk_toggle_button_set_active (node_button, FALSE);
4195 helper->current_priority = button;
4197 gboolean found = FALSE;
4198 /* If no one is active, activate it again */
4199 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4200 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4201 if (gtk_toggle_button_get_active (node_button)) {
4207 gtk_toggle_button_set_active (button, TRUE);
4213 on_format_toggle (GtkToggleButton *button,
4214 MessageSettingsHelper *helper)
4217 ModestMsgEditWindowPrivate *priv;
4219 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4220 if (gtk_toggle_button_get_active (button)) {
4222 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4223 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4224 if ((node_button != button) &&
4225 gtk_toggle_button_get_active (node_button)) {
4226 gtk_toggle_button_set_active (node_button, FALSE);
4229 helper->current_format = button;
4231 gboolean found = FALSE;
4232 /* If no one is active, activate it again */
4233 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4234 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4235 if (gtk_toggle_button_get_active (node_button)) {
4241 gtk_toggle_button_set_active (button, TRUE);
4248 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4253 GtkWidget *priority_hbox;
4254 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4255 GtkWidget *captioned;
4256 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4257 GtkWidget *format_hbox;
4258 GtkWidget *html_toggle, *text_toggle;
4259 ModestMsgEditWindowPrivate *priv;
4260 MessageSettingsHelper helper = {0,};
4262 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4263 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4264 helper.window = window;
4265 helper.priority_group = NULL;
4266 helper.format_group = NULL;
4268 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4269 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4271 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4272 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4273 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4274 vbox = gtk_vbox_new (FALSE, 0);
4275 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4276 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4277 gtk_container_add (GTK_CONTAINER (align), vbox);
4278 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4279 gtk_widget_show (align);
4280 gtk_widget_show (vbox);
4282 /* Priority toggles */
4283 priority_hbox = gtk_hbox_new (TRUE, 0);
4284 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4285 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4286 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4287 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4288 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4289 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4290 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4291 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4292 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4293 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4294 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4295 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4296 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4297 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4298 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4299 gtk_widget_show_all (priority_hbox);
4300 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4301 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4302 gtk_widget_show (captioned);
4303 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4305 /* format toggles */
4306 format_hbox = gtk_hbox_new (TRUE, 0);
4307 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4308 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4309 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4310 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4311 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4312 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4313 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4314 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4315 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4316 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4317 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4318 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4319 gtk_widget_show_all (format_hbox);
4320 gtk_widget_show (format_hbox);
4321 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4324 g_object_unref (title_sizegroup);
4325 g_object_unref (value_sizegroup);
4327 /* Set current values */
4328 switch (priv->priority_flags) {
4329 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4330 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4331 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4333 case TNY_HEADER_FLAG_LOW_PRIORITY:
4334 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4335 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4338 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4339 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4343 switch (modest_msg_edit_window_get_format (window)) {
4344 case MODEST_MSG_EDIT_FORMAT_TEXT:
4345 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4346 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4348 case MODEST_MSG_EDIT_FORMAT_HTML:
4350 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4351 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4355 /* Signal connects */
4356 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4357 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4358 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4359 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4360 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4362 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4363 GTK_WINDOW (dialog), GTK_WINDOW (window));
4365 /* Save settings if the user clicked on done */
4366 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4367 TnyHeaderFlags flags;
4368 ModestMsgEditFormat old_format, new_format;
4370 /* Set priority flags */
4371 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4372 if (priv->priority_flags != flags)
4373 modest_msg_edit_window_set_priority_flags (window, flags);
4375 /* Set edit format */
4376 old_format = modest_msg_edit_window_get_format (window);
4377 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4378 if (old_format != new_format) {
4379 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4380 modest_msg_edit_window_set_file_format (window, file_format);
4384 gtk_widget_destroy (dialog);
4385 g_slist_free (helper.priority_group);
4389 on_message_settings (GtkAction *action,
4390 ModestMsgEditWindow *window)
4392 modest_msg_edit_window_show_msg_settings_dialog (window);
4396 on_show_toolbar_button_toggled (HildonCheckButton *button,
4397 ModestMsgEditWindow *window)
4399 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4401 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4402 hildon_check_button_get_active (button));
4406 on_cc_button_toggled (HildonCheckButton *button,
4407 ModestMsgEditWindow *window)
4409 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4411 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4412 hildon_check_button_get_active (button));
4416 on_bcc_button_toggled (HildonCheckButton *button,
4417 ModestMsgEditWindow *window)
4419 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4421 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4422 hildon_check_button_get_active (button));
4426 setup_menu (ModestMsgEditWindow *self)
4428 ModestMsgEditWindowPrivate *priv = NULL;
4430 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4432 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4434 /* Settings menu buttons */
4435 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4436 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4438 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4439 APP_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4440 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4441 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4442 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4443 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4445 priv->cc_button = hildon_check_button_new (0);
4446 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4447 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4449 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4451 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4452 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4453 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4454 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4456 priv->bcc_button = hildon_check_button_new (0);
4457 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4458 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4460 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4462 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4463 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4464 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4465 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4467 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4468 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4470 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4471 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4472 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4473 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4474 APP_MENU_CALLBACK (on_message_settings),
4476 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4477 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4479 priv->show_toolbar_button = hildon_check_button_new (0);
4480 gtk_button_set_label (GTK_BUTTON (priv->show_toolbar_button), _("mcen_bd_show_toolbar"));
4481 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
4483 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->show_toolbar_button),
4484 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4485 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4486 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4487 gtk_button_set_alignment (GTK_BUTTON (priv->show_toolbar_button), 0.5, 0.5);
4488 gtk_button_set_alignment (GTK_BUTTON (priv->show_toolbar_button), 0.5, 0.5);
4493 emit_open_addressbook (GtkButton *button,
4494 ModestRecptEditor *editor)
4496 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4500 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4501 const gchar *label, GtkWidget *control)
4503 GtkWidget *abook_button;
4506 GtkWidget *label_widget;
4508 box = gtk_hbox_new (FALSE, 0);
4510 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4511 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4513 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4514 label_widget = gtk_label_new (label);
4515 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4516 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4518 gtk_container_add (GTK_CONTAINER (align), abook_button);
4519 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4520 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4521 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4522 if (title_size_group)
4523 gtk_size_group_add_widget (title_size_group, label_widget);
4524 if (value_size_group)
4525 gtk_size_group_add_widget (value_size_group, control);
4527 g_signal_connect (G_OBJECT (abook_button), "clicked",
4528 G_CALLBACK (emit_open_addressbook), control);
4534 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4536 ModestMsgEditWindowPrivate *priv = NULL;
4538 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4540 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4541 priv->max_chars_banner = NULL;
4545 has_pending_addresses (ModestRecptEditor *recpt_editor)
4547 const gchar *recipients = NULL;
4548 GSList *start_indexes = NULL, *end_indexes = NULL;
4549 GSList *current_start, *current_end;
4550 GtkTextBuffer *buffer;
4551 gint offset_delta = 0;
4553 gboolean has_recipients_to_add = FALSE;
4555 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4556 last_length = g_utf8_strlen (recipients, -1);
4557 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4562 current_start = start_indexes;
4563 current_end = end_indexes;
4564 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4566 while (current_start && !has_recipients_to_add) {
4568 gchar *start_ptr, *end_ptr;
4569 gint start_pos, end_pos;
4571 start_pos = (*((gint*) current_start->data)) + offset_delta;
4572 end_pos = (*((gint*) current_end->data)) + offset_delta;
4574 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4575 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4577 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4579 if (modest_text_utils_validate_recipient (address, NULL)) {
4580 if (!modest_address_book_has_address (address)) {
4581 has_recipients_to_add = TRUE;
4584 current_start = g_slist_next (current_start);
4585 current_end = g_slist_next (current_end);
4587 return has_recipients_to_add;
4591 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4593 ModestMsgEditWindowPrivate *priv = NULL;
4595 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4599 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4600 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4601 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))
4608 modest_msg_edit_window_set_custom_header_pairs (ModestMsgEditWindow *self,
4609 TnyList *header_pairs)
4611 ModestMsgEditWindowPrivate *priv = NULL;
4613 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
4614 g_return_if_fail (TNY_IS_LIST (header_pairs));
4616 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4617 g_object_unref (priv->custom_header_pairs);
4618 priv->custom_header_pairs = tny_list_copy (header_pairs);