1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 128*1024
97 #define MAX_BODY_LINES 2048
99 static gboolean is_wp_text_buffer_started = FALSE;
101 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
102 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
103 static void modest_msg_edit_window_finalize (GObject *obj);
105 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
106 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
107 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
109 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
110 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
111 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
112 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
113 GtkTextIter *start, GtkTextIter *end,
115 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
116 static void body_insert_text (GtkTextBuffer *buffer,
117 GtkTextIter *location,
120 ModestMsgEditWindow *window);
121 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
122 static void subject_field_insert_text (GtkEditable *editable,
124 gint new_text_length,
126 ModestMsgEditWindow *window);
127 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
129 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
131 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
132 ModestRecptEditor *editor);
133 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
134 ModestMsgEditWindow *window);
136 /* ModestWindow methods implementation */
137 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
138 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
139 gboolean show_toolbar);
140 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
142 ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
144 static void subject_field_move_cursor (GtkEntry *entry,
145 GtkMovementStep step,
149 static void update_window_title (ModestMsgEditWindow *window);
152 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
153 ModestMsgEditWindow *window);
154 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
155 ModestMsgEditWindow *window);
156 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
158 GtkTextIter *match_start,
159 GtkTextIter *match_end);
161 static void remove_tags (WPTextBuffer *buffer);
163 static void on_account_removed (TnyAccountStore *account_store,
167 static void init_window (ModestMsgEditWindow *obj);
169 gboolean scroll_drag_timeout (gpointer userdata);
170 static void correct_scroll (ModestMsgEditWindow *w);
171 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
172 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
173 ModestMsgEditWindow *userdata);
174 static void text_buffer_mark_set (GtkTextBuffer *buffer,
177 ModestMsgEditWindow *userdata);
178 static void on_message_settings (GtkAction *action,
179 ModestMsgEditWindow *window);
180 static void setup_menu (ModestMsgEditWindow *self);
182 static void from_field_changed (HildonPickerButton *button,
183 ModestMsgEditWindow *self);
184 static void font_size_clicked (GtkToolButton *button,
185 ModestMsgEditWindow *window);
186 static void font_face_clicked (GtkToolButton *button,
187 ModestMsgEditWindow *window);
188 static void update_signature (ModestMsgEditWindow *self,
189 const gchar *old_account,
190 const gchar *new_account);
191 static void update_branding (ModestMsgEditWindow *self,
192 const gchar *new_account);
193 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
194 const gchar *label, GtkWidget *control);
195 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
196 static void DEBUG_BUFFER (WPTextBuffer *buffer)
200 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
202 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
203 while (!gtk_text_iter_is_end (&iter)) {
204 GString *output = g_string_new ("");
205 GSList *toggled_tags;
208 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
209 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
210 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
211 GtkTextTag *tag = (GtkTextTag *) node->data;
213 g_object_get (G_OBJECT (tag), "name", &name, NULL);
214 output = g_string_append (output, name);
215 g_string_append (output, " ");
217 output = g_string_append (output, "] OPENED [ ");
218 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
219 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
220 GtkTextTag *tag = (GtkTextTag *) node->data;
222 g_object_get (G_OBJECT (tag), "name", &name, NULL);
223 output = g_string_append (output, name);
224 g_string_append (output, " ");
226 output = g_string_append (output, "]\n");
227 g_debug ("%s", output->str);
228 g_string_free (output, TRUE);
229 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
231 g_debug ("END BUFFER");
235 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
236 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
240 /* static gboolean */
241 /* on_key_pressed (GtkWidget *self, */
242 /* GdkEventKey *event, */
243 /* gpointer user_data); */
245 /* list my signals */
252 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
253 struct _ModestMsgEditWindowPrivate {
255 GtkWidget *header_box;
257 ModestPairList *from_field_protos;
258 GtkWidget *from_field;
259 gchar *last_from_account;
260 gchar *original_account_name;
265 gchar *original_mailbox;
269 GtkWidget *bcc_field;
270 GtkWidget *subject_field;
271 GtkWidget *attachments_view;
272 GtkWidget *priority_icon;
273 GtkWidget *subject_box;
274 GtkWidget *send_button;
276 GtkWidget *cc_caption;
277 GtkWidget *bcc_caption;
278 gboolean update_caption_visibility;
279 GtkWidget *attachments_caption;
281 GtkTextBuffer *text_buffer;
283 GtkWidget *font_size_toolitem;
284 GtkWidget *font_face_toolitem;
285 GtkWidget *font_color_button;
286 GtkWidget *font_color_toolitem;
287 GSList *font_items_group;
288 GtkTreeModel *faces_model;
289 gint current_face_index;
290 GtkWidget *font_tool_button_label;
291 GtkTreeModel *sizes_model;
292 gint current_size_index;
293 GtkWidget *size_tool_button_label;
295 GtkWidget *find_toolbar;
298 GtkWidget *font_dialog;
301 guint correct_scroll_idle;
302 guint scroll_drag_timeout_id;
306 TnyList *attachments;
311 TnyHeaderFlags priority_flags;
313 gboolean can_undo, can_redo;
314 gulong clipboard_change_handler_id;
315 gulong default_clipboard_change_handler_id;
316 gulong account_removed_handler_id;
317 guint clipboard_owner_idle;
318 gchar *clipboard_text;
327 GtkWidget *cc_button;
328 GtkWidget *bcc_button;
330 GtkWidget *max_chars_banner;
332 GtkWidget *brand_icon;
333 GtkWidget *brand_label;
334 GtkWidget *brand_container;
337 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
338 MODEST_TYPE_MSG_EDIT_WINDOW, \
339 ModestMsgEditWindowPrivate))
341 static GtkWindowClass *parent_class = NULL;
343 /* uncomment the following if you have defined any signals */
344 /* static guint signals[LAST_SIGNAL] = {0}; */
347 modest_msg_edit_window_get_type (void)
349 static GType my_type = 0;
351 static const GTypeInfo my_info = {
352 sizeof(ModestMsgEditWindowClass),
353 NULL, /* base init */
354 NULL, /* base finalize */
355 (GClassInitFunc) modest_msg_edit_window_class_init,
356 NULL, /* class finalize */
357 NULL, /* class data */
358 sizeof(ModestMsgEditWindow),
360 (GInstanceInitFunc) modest_msg_edit_window_init,
363 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
364 "ModestMsgEditWindow",
372 save_state (ModestWindow *self)
374 modest_widget_memory_save (modest_runtime_get_conf(),
375 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
380 restore_settings (ModestMsgEditWindow *self)
382 ModestConf *conf = NULL;
384 conf = modest_runtime_get_conf ();
386 /* Dim at start clipboard actions */
387 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
392 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
394 GObjectClass *gobject_class;
395 ModestWindowClass *modest_window_class;
396 gobject_class = (GObjectClass*) klass;
397 modest_window_class = (ModestWindowClass*) klass;
399 parent_class = g_type_class_peek_parent (klass);
400 gobject_class->finalize = modest_msg_edit_window_finalize;
402 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
403 modest_window_class->save_state_func = save_state;
404 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
406 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
410 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
412 ModestMsgEditWindowPrivate *priv;
413 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
415 priv->msg_body = NULL;
416 priv->from_field = NULL;
417 priv->to_field = NULL;
418 priv->cc_field = NULL;
419 priv->bcc_field = NULL;
420 priv->subject_field = NULL;
421 priv->attachments = TNY_LIST (tny_simple_list_new ());
422 priv->images = TNY_LIST (tny_simple_list_new ());
423 priv->images_size = 0;
424 priv->images_count = 0;
427 priv->cc_caption = NULL;
428 priv->bcc_caption = NULL;
429 priv->update_caption_visibility = FALSE;
431 priv->priority_flags = 0;
433 priv->find_toolbar = NULL;
434 priv->last_search = NULL;
436 priv->draft_msg = NULL;
437 priv->outbox_msg = NULL;
438 priv->msg_uid = NULL;
440 priv->can_undo = FALSE;
441 priv->can_redo = FALSE;
442 priv->clipboard_change_handler_id = 0;
443 priv->default_clipboard_change_handler_id = 0;
444 priv->account_removed_handler_id = 0;
445 priv->clipboard_owner_idle = 0;
446 priv->clipboard_text = NULL;
449 priv->scroll_drag_timeout_id = 0;
450 priv->correct_scroll_idle = 0;
451 priv->last_upper = 0.0;
453 priv->font_dialog = NULL;
454 priv->app_menu = NULL;
456 priv->references = NULL;
457 priv->in_reply_to = NULL;
458 priv->max_chars_banner = NULL;
460 if (!is_wp_text_buffer_started) {
461 is_wp_text_buffer_started = TRUE;
462 wp_text_buffer_library_init ();
467 hildon_program_add_window (hildon_program_get_instance(),
472 multimailbox_get_default_mailbox (const gchar *account_name)
474 gchar *transport_account;
475 gchar *result = NULL;
477 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
479 TNY_ACCOUNT_TYPE_TRANSPORT);
480 if (transport_account) {
482 ModestProtocolRegistry *registry;
484 registry = modest_runtime_get_protocol_registry ();
486 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
487 MODEST_ACCOUNT_PROTO, TRUE);
489 ModestProtocol *protocol =
490 modest_protocol_registry_get_protocol_by_name (registry,
491 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
493 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
494 ModestPairList *pair_list;
496 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
499 ModestPair *pair = (ModestPair *) pair_list->data;
500 result = g_strdup ((const gchar *) pair->first);
501 modest_pair_list_free (pair_list);
512 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
514 static ModestPairList*
515 get_transports (void)
517 GSList *transports = NULL;
519 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
520 GSList *accounts = modest_account_mgr_account_names (account_mgr,
521 TRUE /* only enabled accounts. */);
523 GSList *cursor = accounts;
525 gchar *account_name = cursor->data;
528 gchar *transport_account;
529 gboolean multi_mailbox = FALSE;
530 ModestProtocol *protocol = NULL;
532 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
534 transport_account = modest_account_mgr_get_server_account_name
535 (modest_runtime_get_account_mgr (),
537 TNY_ACCOUNT_TYPE_TRANSPORT);
538 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
539 ModestPairList *pair_list;
540 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
543 transports = g_slist_concat (transports, pair_list);
544 multi_mailbox = TRUE;
549 if (!multi_mailbox) {
550 gchar *from_string = NULL;
552 from_string = modest_account_mgr_get_from_string (account_mgr,
554 if (from_string && account_name) {
555 gchar *name = account_name;
556 ModestPair *pair = modest_pair_new ((gpointer) name,
557 (gpointer) from_string , TRUE);
558 transports = g_slist_prepend (transports, pair);
563 cursor = cursor->next;
565 g_slist_free (accounts); /* only free the accounts, not the elements,
566 * because they are used in the pairlist */
570 static void window_focus (GtkWindow *window,
574 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
578 scroll_drag_timeout (gpointer userdata)
580 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
581 ModestMsgEditWindowPrivate *priv;
583 /* It could happen that the window was already closed */
584 if (!GTK_WIDGET_VISIBLE (win))
587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
589 correct_scroll_without_drag_check (win, TRUE);
591 priv->scroll_drag_timeout_id = 0;
597 correct_scroll_without_drag_check_idle (gpointer userdata)
599 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
600 ModestMsgEditWindowPrivate *priv;
602 GdkRectangle rectangle;
603 gint offset_min, offset_max;
607 /* It could happen that the window was already closed */
608 if (!GTK_WIDGET_VISIBLE (w))
611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
613 insert = gtk_text_buffer_get_insert (priv->text_buffer);
614 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
616 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
617 offset_min = priv->msg_body->allocation.y + rectangle.y;
618 offset_max = offset_min + rectangle.height;
620 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
621 offset_min = MAX (offset_min - 48, 0);
622 offset_max = MIN (offset_max + 48, vadj->upper);
624 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
626 priv->correct_scroll_idle = 0;
631 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
633 ModestMsgEditWindowPrivate *priv;
635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
637 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
640 if (priv->correct_scroll_idle > 0) {
644 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
645 (GSourceFunc) correct_scroll_without_drag_check_idle,
651 correct_scroll (ModestMsgEditWindow *w)
653 ModestMsgEditWindowPrivate *priv;
655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
656 if (gtk_grab_get_current () == priv->msg_body) {
657 if (priv->scroll_drag_timeout_id == 0) {
658 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
660 (GSourceFunc) scroll_drag_timeout,
667 correct_scroll_without_drag_check (w, TRUE);
671 text_buffer_end_user_action (GtkTextBuffer *buffer,
672 ModestMsgEditWindow *userdata)
675 correct_scroll (userdata);
679 text_buffer_mark_set (GtkTextBuffer *buffer,
682 ModestMsgEditWindow *userdata)
684 gtk_text_buffer_begin_user_action (buffer);
685 gtk_text_buffer_end_user_action (buffer);
689 cut_clipboard_check (GtkTextView *text_view,
692 GtkTextBuffer *buffer;
694 buffer = gtk_text_view_get_buffer (text_view);
695 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
696 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
701 copy_clipboard_check (GtkTextView *text_view,
704 GtkTextBuffer *buffer;
706 buffer = gtk_text_view_get_buffer (text_view);
707 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
708 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
713 attachment_deleted (ModestAttachmentsView *attachments_view,
716 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
721 connect_signals (ModestMsgEditWindow *obj)
723 ModestMsgEditWindowPrivate *priv;
725 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
727 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
728 G_CALLBACK (text_buffer_refresh_attributes), obj);
729 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
730 G_CALLBACK (text_buffer_can_undo), obj);
731 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
732 G_CALLBACK (text_buffer_can_redo), obj);
733 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
734 G_CALLBACK (body_changed), obj);
735 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
736 G_CALLBACK (body_insert_text), obj);
737 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
738 G_CALLBACK (body_changed), obj);
739 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
740 G_CALLBACK (text_buffer_end_user_action), obj);
741 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
742 G_CALLBACK (text_buffer_mark_set), obj);
743 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
744 G_CALLBACK (text_buffer_apply_tag), obj);
745 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
746 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
747 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
748 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
749 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
750 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
752 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
753 G_CALLBACK (modest_ui_actions_on_send), obj);
755 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
756 G_CALLBACK (from_field_changed), obj);
758 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
759 G_CALLBACK (msg_body_focus), obj);
760 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
761 G_CALLBACK (msg_body_focus), obj);
762 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
763 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
764 "changed", G_CALLBACK (recpt_field_changed), obj);
765 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
766 "changed", G_CALLBACK (recpt_field_changed), obj);
767 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
768 "changed", G_CALLBACK (recpt_field_changed), obj);
769 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
770 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
771 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
773 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
774 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
776 priv->clipboard_change_handler_id =
777 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
778 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
779 priv->default_clipboard_change_handler_id =
780 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
781 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
783 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
784 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
785 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
789 init_wp_text_view_style ()
791 static gboolean initialized = FALSE;
794 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
800 init_window (ModestMsgEditWindow *obj)
802 GtkWidget *to_caption, *subject_caption;
803 GtkWidget *main_vbox;
804 ModestMsgEditWindowPrivate *priv;
805 GtkActionGroup *action_group;
806 ModestWindowPrivate *parent_priv;
807 GdkPixbuf *window_icon = NULL;
808 GError *error = NULL;
810 GtkSizeGroup *title_size_group;
811 GtkSizeGroup *value_size_group;
812 GtkWidget *window_box;
813 GtkWidget *window_align;
814 #if (GTK_MINOR_VERSION >= 10)
815 GdkAtom deserialize_type;
817 GtkWidget *from_send_hbox;
818 GtkWidget *send_icon;
819 GtkWidget *attachments_label;
820 GtkWidget *branding_box;
822 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
823 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
825 parent_priv->ui_manager = gtk_ui_manager_new();
826 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
827 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
829 /* Add common actions */
830 gtk_action_group_add_actions (action_group,
831 modest_msg_edit_action_entries,
832 G_N_ELEMENTS (modest_msg_edit_action_entries),
834 gtk_action_group_add_actions (action_group,
835 hildon2_msg_edit_action_entries,
836 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
838 gtk_action_group_add_toggle_actions (action_group,
839 modest_msg_edit_toggle_action_entries,
840 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
842 gtk_action_group_add_radio_actions (action_group,
843 modest_msg_edit_alignment_radio_action_entries,
844 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
846 G_CALLBACK (modest_ui_actions_on_change_justify),
848 gtk_action_group_add_radio_actions (action_group,
849 modest_msg_edit_priority_action_entries,
850 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
852 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
854 gtk_action_group_add_radio_actions (action_group,
855 modest_msg_edit_file_format_action_entries,
856 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
857 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
858 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
860 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
861 g_object_unref (action_group);
863 /* Load the UI definition */
864 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
867 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
868 g_clear_error (&error);
871 /* Add accelerators */
872 gtk_window_add_accel_group (GTK_WINDOW (obj),
873 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
875 parent_priv->menubar = NULL;
877 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
878 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
880 /* Note: This ModestPairList* must exist for as long as the picker
881 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
882 * so it can't know how to manage its memory. */
883 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
884 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
886 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
887 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
888 _("mail_va_from"), priv->from_field);
889 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
890 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
891 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
893 priv->to_field = modest_recpt_editor_new ();
894 priv->cc_field = modest_recpt_editor_new ();
895 priv->bcc_field = modest_recpt_editor_new ();
896 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
897 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
898 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
899 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
900 priv->priority_icon = gtk_image_new ();
901 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
902 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
903 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
904 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
905 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
906 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
907 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
908 priv->attachments_view = modest_attachments_view_new (NULL);
909 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
910 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
912 priv->header_box = gtk_vbox_new (FALSE, 0);
914 to_caption = _create_addressbook_box
915 (title_size_group, value_size_group,
916 _("mail_va_to"), priv->to_field);
917 priv->cc_caption = _create_addressbook_box
918 (title_size_group, value_size_group,
919 _("mail_va_cc"), priv->cc_field);
920 priv->bcc_caption = _create_addressbook_box
921 (title_size_group, value_size_group,
922 _("mail_va_hotfix1"), priv->bcc_field);
923 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
924 _("mail_va_subject"), FALSE, priv->subject_box);
925 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
926 _("mail_va_attachment"),
928 priv->attachments_view,
929 HILDON_SIZE_AUTO_WIDTH |
930 HILDON_SIZE_AUTO_HEIGHT);
931 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
932 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
935 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
936 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
937 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
938 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
940 g_object_unref (title_size_group);
941 g_object_unref (value_size_group);
943 priv->brand_icon = gtk_image_new ();
944 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
945 priv->brand_label = gtk_label_new (NULL);
946 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
947 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
948 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
949 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
951 from_send_hbox = gtk_hbox_new (FALSE, 0);
952 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
953 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
955 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
956 gtk_widget_show (branding_box);
957 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
958 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
960 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
961 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
962 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
963 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
966 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
967 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
968 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
969 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
970 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
971 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
972 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
973 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
975 init_wp_text_view_style ();
977 priv->msg_body = modest_wp_text_view_new ();
980 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
981 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
982 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
983 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
984 #if (GTK_MINOR_VERSION >= 10)
985 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
986 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
988 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
989 deserialize_type, TRUE);
991 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
993 priv->find_toolbar = hildon_find_toolbar_new (NULL);
994 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
996 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
998 priv->pannable = hildon_pannable_area_new ();
1000 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1002 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1003 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1004 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1006 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1007 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1008 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1010 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1011 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1013 window_box = gtk_vbox_new (FALSE, 0);
1014 gtk_container_add (GTK_CONTAINER(obj), window_box);
1016 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1018 /* Set window icon */
1019 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1021 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1022 g_object_unref (window_icon);
1027 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1029 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1031 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1032 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1033 priv->clipboard_change_handler_id))
1034 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1035 priv->clipboard_change_handler_id);
1036 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1037 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1038 priv->default_clipboard_change_handler_id))
1039 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1040 priv->default_clipboard_change_handler_id);
1042 if (priv->account_removed_handler_id &&
1043 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1044 priv->account_removed_handler_id))
1045 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1046 priv->account_removed_handler_id);
1050 modest_msg_edit_window_finalize (GObject *obj)
1052 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1054 if (priv->max_chars_banner) {
1055 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1056 priv->max_chars_banner = FALSE;
1059 /* Sanity check: shouldn't be needed, the window mgr should
1060 call this function before */
1061 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1063 if (priv->font_dialog != NULL) {
1064 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1067 if (priv->clipboard_text != NULL) {
1068 g_free (priv->clipboard_text);
1069 priv->clipboard_text = NULL;
1072 if (priv->draft_msg != NULL) {
1073 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1074 if (TNY_IS_HEADER (header)) {
1075 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1076 modest_window_mgr_unregister_header (mgr, header);
1078 g_object_unref (priv->draft_msg);
1079 priv->draft_msg = NULL;
1081 if (priv->outbox_msg != NULL) {
1082 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1083 if (TNY_IS_HEADER (header)) {
1084 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1085 modest_window_mgr_unregister_header (mgr, header);
1087 g_object_unref (priv->outbox_msg);
1088 priv->outbox_msg = NULL;
1090 if (priv->correct_scroll_idle > 0) {
1091 g_source_remove (priv->correct_scroll_idle);
1092 priv->correct_scroll_idle = 0;
1094 if (priv->scroll_drag_timeout_id > 0) {
1095 g_source_remove (priv->scroll_drag_timeout_id);
1096 priv->scroll_drag_timeout_id = 0;
1098 if (priv->clipboard_owner_idle > 0) {
1099 g_source_remove (priv->clipboard_owner_idle);
1100 priv->clipboard_owner_idle = 0;
1102 if (priv->original_account_name)
1103 g_free (priv->original_account_name);
1104 if (priv->original_mailbox)
1105 g_free (priv->original_mailbox);
1106 g_free (priv->msg_uid);
1107 g_free (priv->last_search);
1108 g_free (priv->references);
1109 g_free (priv->in_reply_to);
1110 g_object_unref (priv->attachments);
1111 g_object_unref (priv->images);
1113 /* This had to stay alive for as long as the picker that used it: */
1114 modest_pair_list_free (priv->from_field_protos);
1116 G_OBJECT_CLASS(parent_class)->finalize (obj);
1120 pixbuf_size_prepared (GdkPixbufLoader *loader,
1123 ModestMsgEditWindow *self)
1125 gint new_height, new_width;
1128 new_height = height;
1132 if (width > IMAGE_MAX_WIDTH) {
1133 new_height = height * IMAGE_MAX_WIDTH / width;
1134 new_width = IMAGE_MAX_WIDTH;
1137 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1141 pixbuf_from_stream (TnyStream *stream,
1142 const gchar *mime_type,
1143 guint64 *stream_size,
1144 ModestMsgEditWindow *self)
1146 GdkPixbufLoader *loader;
1149 GError *error = NULL;
1153 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1155 if (loader == NULL) {
1160 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1162 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1164 tny_stream_reset (TNY_STREAM (stream));
1165 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1166 unsigned char read_buffer[128];
1168 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1170 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1173 /* Allow some UI responsiveness */
1174 while (gtk_events_pending ())
1175 gtk_main_iteration ();
1177 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1179 gdk_pixbuf_loader_close (loader, &error);
1182 g_error_free (error);
1183 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1185 g_object_ref (pixbuf);
1186 g_object_unref (loader);
1191 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1192 GdkPixbuf *new_pixbuf;
1194 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1195 gdk_pixbuf_get_width (pixbuf);
1196 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1197 g_object_unref (pixbuf);
1198 pixbuf = new_pixbuf;
1202 *stream_size = size;
1208 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1210 ModestMsgEditWindowPrivate *priv;
1213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1215 g_object_ref (self);
1216 for (iter = tny_list_create_iterator (attachments);
1217 !tny_iterator_is_done (iter);
1218 tny_iterator_next (iter)) {
1219 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1220 const gchar *cid = tny_mime_part_get_content_id (part);
1221 const gchar *mime_type = tny_mime_part_get_content_type (part);
1222 if ((cid != NULL)&&(mime_type != NULL)) {
1223 guint64 stream_size;
1224 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1225 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1228 g_object_unref (stream);
1230 if (pixbuf != NULL) {
1231 priv->images_count ++;
1232 priv->images_size += stream_size;
1233 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1234 g_object_unref (pixbuf);
1237 g_object_unref (part);
1239 g_object_unref (iter);
1240 g_object_unref (self);
1244 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1246 TnyMimePart *parent = NULL;
1247 const gchar *content_type = NULL;
1248 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1250 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1252 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1253 parent = g_object_ref (msg);
1254 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1255 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1258 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1259 iter = tny_list_create_iterator (parts);
1260 while (!tny_iterator_is_done (iter)) {
1262 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1263 content_type = tny_mime_part_get_content_type (part);
1264 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1268 g_object_unref (part);
1270 tny_iterator_next (iter);
1272 g_object_unref (iter);
1273 g_object_unref (parts);
1276 if (parent != NULL) {
1277 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1280 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1281 iter = tny_list_create_iterator (parts);
1282 while (!tny_iterator_is_done (iter)) {
1284 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1285 content_type = tny_mime_part_get_content_type (part);
1286 if (content_type && g_str_has_prefix (content_type, "image/")) {
1287 tny_list_prepend (priv->images, (GObject *) part);
1289 g_object_unref (part);
1290 tny_iterator_next (iter);
1292 g_object_unref (iter);
1293 g_object_unref (parts);
1294 g_object_unref (parent);
1299 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1302 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1304 for (iter = tny_list_create_iterator (attachments) ;
1305 !tny_iterator_is_done (iter);
1306 tny_iterator_next (iter)) {
1307 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1308 const gchar *cid = tny_mime_part_get_content_id (part);
1310 char *invalid = NULL;
1311 gint int_cid = strtol (cid, &invalid, 10);
1312 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1313 priv->next_cid = int_cid + 1;
1316 g_object_unref (part);
1318 g_object_unref (iter);
1322 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1325 gchar *to, *cc, *bcc, *subject;
1327 ModestMsgEditWindowPrivate *priv;
1328 ModestWindowPrivate *parent_priv;
1330 TnyHeaderFlags priority_flags;
1331 TnyFolder *msg_folder;
1332 gboolean is_html = FALSE;
1333 gboolean field_view_set;
1335 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1336 g_return_if_fail (TNY_IS_MSG (msg));
1338 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1339 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1341 header = tny_msg_get_header (msg);
1342 to = tny_header_dup_to (header);
1343 cc = tny_header_dup_cc (header);
1344 bcc = tny_header_dup_bcc (header);
1345 subject = tny_header_dup_subject (header);
1347 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1348 priority_flags = tny_header_get_priority (header);
1351 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1353 field_view_set = TRUE;
1355 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1356 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1357 gtk_widget_show (priv->cc_caption);
1358 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1359 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1360 gtk_widget_hide (priv->cc_caption);
1361 field_view_set = FALSE;
1363 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1365 field_view_set = TRUE;
1367 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1368 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1369 gtk_widget_show (priv->bcc_caption);
1370 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1371 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1372 gtk_widget_hide (priv->bcc_caption);
1373 field_view_set = FALSE;
1375 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1379 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1380 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1383 update_window_title (self);
1385 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1386 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1388 if ((body == NULL)||(body[0] == '\0')) {
1390 body = modest_text_utils_convert_to_html ("");
1393 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1394 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1397 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1400 /* Add attachments to the view */
1401 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1402 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1403 if (tny_list_get_length (priv->attachments) == 0) {
1404 gtk_widget_hide (priv->attachments_caption);
1406 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1407 gtk_widget_show_all (priv->attachments_caption);
1409 get_related_images (self, msg);
1410 update_next_cid (self, priv->attachments);
1411 update_next_cid (self, priv->images);
1412 replace_with_images (self, priv->images);
1414 if (preserve_is_rich && !is_html) {
1415 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1416 /* Get the default format required from configuration */
1417 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1418 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1421 /* Set the default focus depending on having already a To: field or not */
1422 if ((!to)||(*to == '\0')) {
1423 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1425 gtk_widget_grab_focus (priv->msg_body);
1428 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1430 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1431 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1433 modest_msg_edit_window_set_modified (self, FALSE);
1435 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1436 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1437 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1438 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1440 if (priv->msg_uid) {
1441 g_free (priv->msg_uid);
1442 priv->msg_uid = NULL;
1445 /* we should set a reference to the incoming message if it is a draft */
1446 msg_folder = tny_msg_get_folder (msg);
1448 if (modest_tny_folder_is_local_folder (msg_folder)) {
1449 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1450 if (type == TNY_FOLDER_TYPE_INVALID)
1451 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1453 if (type == TNY_FOLDER_TYPE_DRAFTS)
1454 priv->draft_msg = g_object_ref(msg);
1455 if (type == TNY_FOLDER_TYPE_OUTBOX)
1456 priv->outbox_msg = g_object_ref(msg);
1457 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1459 g_object_unref (msg_folder);
1470 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1472 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1473 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1474 GtkWidget *placeholder;
1475 GtkWidget *tool_item;
1480 GtkWidget *sizes_menu;
1481 GtkWidget *fonts_menu;
1487 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1488 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1489 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1490 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1492 /* Font color placeholder */
1493 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1494 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1497 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1498 priv->font_color_button = hildon_color_button_new ();
1499 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1500 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1501 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1502 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1503 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1504 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1505 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1506 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1508 G_CALLBACK (modest_msg_edit_window_color_button_change),
1511 /* Font size and face placeholder */
1512 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1513 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1515 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1516 priv->size_tool_button_label = gtk_label_new (NULL);
1517 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1518 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1519 size_text, "</span>", NULL);
1520 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1521 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1523 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1524 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1525 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1526 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1527 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1528 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1529 gtk_widget_set_sensitive (arrow, FALSE);
1530 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1531 sizes_menu = gtk_menu_new ();
1532 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1533 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1536 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1537 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1539 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1543 if (wp_font_size[size_index] == 12)
1544 priv->current_size_index = size_index;
1548 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1549 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1550 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1551 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1552 priv->font_size_toolitem = tool_item;
1555 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1556 priv->font_tool_button_label = gtk_label_new (NULL);
1557 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1558 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1559 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1561 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1562 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1563 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1564 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1565 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1566 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1567 gtk_widget_set_sensitive (arrow, FALSE);
1568 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1569 fonts_menu = gtk_menu_new ();
1570 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1571 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1574 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1576 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1577 0, wp_get_font_name (font_index),
1580 if (font_index == DEFAULT_FONT)
1581 priv->current_face_index = font_index;
1583 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1584 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1585 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1586 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1587 priv->font_face_toolitem = tool_item;
1589 /* Set expand and homogeneous for remaining items */
1590 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1591 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1592 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1593 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1594 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1595 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1597 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1598 will not show the tool items added to the placeholders) */
1599 gtk_widget_show_all (parent_priv->toolbar);
1601 /* Set the no show all *after* showing all items. We do not
1602 want the toolbar to be shown with a show all because it
1603 could go agains the gconf setting regarding showing or not
1604 the toolbar of the editor window */
1605 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1611 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1614 ModestWindowPrivate *parent_priv;
1615 ModestMsgEditWindowPrivate *priv;
1616 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1617 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1618 ModestWindowMgr *mgr = NULL;
1620 g_return_val_if_fail (msg, NULL);
1621 g_return_val_if_fail (account_name, NULL);
1623 mgr = modest_runtime_get_window_mgr ();
1625 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1627 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1628 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1630 /* Menubar. Update the state of some toggles */
1631 priv->from_field_protos = get_transports ();
1632 priv->original_mailbox = NULL;
1633 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1634 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1635 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1636 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1637 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1638 priv->original_mailbox = g_strdup (mailbox);
1639 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1640 /* We set the first mailbox as the active mailbox */
1641 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1642 if (priv->original_mailbox != NULL)
1643 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1644 (gpointer) priv->original_mailbox);
1646 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1647 (gpointer) account_name);
1649 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1651 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1652 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1653 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1655 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1656 hildon_touch_selector_get_current_text
1657 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1658 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1659 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1662 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1664 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1666 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1667 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1669 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1671 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1672 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1673 /* Add common dimming rules */
1674 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1675 modest_msg_edit_window_toolbar_dimming_entries,
1676 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1677 MODEST_WINDOW (obj));
1678 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1679 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1680 MODEST_WINDOW (obj));
1681 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1682 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1683 MODEST_WINDOW (obj));
1684 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1685 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1686 MODEST_WINDOW (obj));
1687 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1688 G_CALLBACK (modest_ui_dimming_rules_on_send),
1689 MODEST_WINDOW (obj));
1690 /* Insert dimming rules group for this window */
1691 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1692 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1694 /* Setup app menu */
1695 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1697 /* Checks the dimming rules */
1698 g_object_unref (toolbar_rules_group);
1699 g_object_unref (clipboard_rules_group);
1700 gtk_widget_hide (priv->priority_icon);
1701 gtk_widget_queue_resize (priv->subject_box);
1702 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1704 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1706 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1707 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1708 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1709 priv->update_caption_visibility = TRUE;
1711 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1713 /* Track account-removed signal, this window should be closed
1714 in the case we're creating a mail associated to the account
1716 priv->account_removed_handler_id =
1717 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1719 G_CALLBACK(on_account_removed),
1722 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1724 return (ModestWindow*) obj;
1728 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1730 GString **string_buffer = (GString **) user_data;
1732 *string_buffer = g_string_append (*string_buffer, buffer);
1738 * @result: A new string which should be freed with g_free().
1741 get_formatted_data (ModestMsgEditWindow *edit_window)
1743 ModestMsgEditWindowPrivate *priv;
1744 GString *string_buffer = g_string_new ("");
1746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1748 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1750 modest_text_utils_hyperlinkify (string_buffer);
1752 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1754 return g_string_free (string_buffer, FALSE);
1759 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1762 const gchar *account_name;
1763 ModestMsgEditWindowPrivate *priv;
1764 TnyIterator *att_iter;
1765 const gchar *picker_active_id;
1767 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1771 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1772 g_return_val_if_fail (picker_active_id, NULL);
1773 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1775 /* don't free these (except from) */
1776 data = g_slice_new0 (MsgData);
1777 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1778 data->account_name = g_strdup (account_name);
1779 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1780 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1781 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1782 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1783 data->references = g_strdup (priv->references);
1784 data->in_reply_to = g_strdup (priv->in_reply_to);
1785 if (priv->draft_msg) {
1786 data->draft_msg = g_object_ref (priv->draft_msg);
1787 } else if (priv->outbox_msg) {
1788 data->draft_msg = g_object_ref (priv->outbox_msg);
1790 data->draft_msg = NULL;
1793 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1795 gtk_text_buffer_get_bounds (buf, &b, &e);
1796 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1798 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1799 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1801 data->html_body = NULL;
1803 /* deep-copy the data */
1804 att_iter = tny_list_create_iterator (priv->attachments);
1805 data->attachments = NULL;
1806 while (!tny_iterator_is_done (att_iter)) {
1807 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1808 if (!(TNY_IS_MIME_PART(part))) {
1809 g_warning ("strange data in attachment list");
1810 g_object_unref (part);
1811 tny_iterator_next (att_iter);
1814 data->attachments = g_list_append (data->attachments,
1816 tny_iterator_next (att_iter);
1818 g_object_unref (att_iter);
1820 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1821 att_iter = tny_list_create_iterator (priv->images);
1822 data->images = NULL;
1823 while (!tny_iterator_is_done (att_iter)) {
1824 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1826 if (!(TNY_IS_MIME_PART(part))) {
1827 g_warning ("strange data in attachment list");
1828 g_object_unref (part);
1829 tny_iterator_next (att_iter);
1832 cid = tny_mime_part_get_content_id (part);
1834 gchar *image_tag_id;
1835 GtkTextTag *image_tag;
1837 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1838 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1839 g_free (image_tag_id);
1841 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1843 ((gtk_text_iter_has_tag (&iter, image_tag))||
1844 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1845 data->images = g_list_append (data->images,
1846 g_object_ref (part));
1848 g_object_unref (part);
1849 tny_iterator_next (att_iter);
1851 g_object_unref (att_iter);
1853 data->priority_flags = priv->priority_flags;
1860 unref_gobject (GObject *obj, gpointer data)
1862 if (!G_IS_OBJECT(obj))
1864 g_object_unref (obj);
1868 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1871 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1879 g_free (data->from);
1880 g_free (data->subject);
1881 g_free (data->plain_body);
1882 g_free (data->html_body);
1883 g_free (data->account_name);
1884 g_free (data->references);
1885 g_free (data->in_reply_to);
1887 if (data->draft_msg != NULL) {
1888 g_object_unref (data->draft_msg);
1889 data->draft_msg = NULL;
1892 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1893 g_list_free (data->attachments);
1894 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1895 g_list_free (data->images);
1897 g_slice_free (MsgData, data);
1901 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1903 guint64 *parts_size)
1905 ModestMsgEditWindowPrivate *priv;
1907 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1909 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1911 /* TODO: add images */
1912 *parts_size += priv->images_size;
1913 *parts_count += priv->images_count;
1918 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1921 ModestMsgEditWindowPrivate *priv = NULL;
1922 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1924 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1926 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1928 return MODEST_MSG_EDIT_FORMAT_HTML;
1930 return MODEST_MSG_EDIT_FORMAT_TEXT;
1934 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1935 ModestMsgEditFormat format)
1937 ModestMsgEditWindowPrivate *priv;
1938 ModestWindowPrivate *parent_priv;
1940 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1941 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1942 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1945 case MODEST_MSG_EDIT_FORMAT_HTML:
1946 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1947 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1949 case MODEST_MSG_EDIT_FORMAT_TEXT:
1950 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1951 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1954 g_return_if_reached ();
1958 ModestMsgEditFormatState *
1959 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1961 ModestMsgEditFormatState *format_state = NULL;
1962 ModestMsgEditWindowPrivate *priv;
1963 WPTextBufferFormat *buffer_format;
1965 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1967 buffer_format = g_new0 (WPTextBufferFormat, 1);
1968 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1970 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1972 format_state = g_new0 (ModestMsgEditFormatState, 1);
1973 format_state->bold = buffer_format->bold&0x1;
1974 format_state->italics = buffer_format->italic&0x1;
1975 format_state->bullet = buffer_format->bullet&0x1;
1976 format_state->color = buffer_format->color;
1977 format_state->font_size = buffer_format->font_size;
1978 format_state->font_family = wp_get_font_name (buffer_format->font);
1979 format_state->justification = buffer_format->justification;
1980 g_free (buffer_format);
1982 return format_state;
1987 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1988 const ModestMsgEditFormatState *format_state)
1990 ModestMsgEditWindowPrivate *priv;
1991 WPTextBufferFormat *buffer_format;
1992 WPTextBufferFormat *current_format;
1994 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1995 g_return_if_fail (format_state != NULL);
1997 buffer_format = g_new0 (WPTextBufferFormat, 1);
1998 current_format = g_new0 (WPTextBufferFormat, 1);
2000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2001 gtk_widget_grab_focus (priv->msg_body);
2002 buffer_format->bold = (format_state->bold != FALSE);
2003 buffer_format->italic = (format_state->italics != FALSE);
2004 buffer_format->color = format_state->color;
2005 buffer_format->font_size = format_state->font_size;
2006 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2007 buffer_format->justification = format_state->justification;
2008 buffer_format->bullet = format_state->bullet;
2010 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2012 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2013 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2014 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2015 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2016 buffer_format->cs.font = (buffer_format->font != current_format->font);
2017 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2018 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2020 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2021 if (buffer_format->cs.bold) {
2022 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2023 GINT_TO_POINTER (buffer_format->bold&0x1));
2025 if (buffer_format->cs.italic) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2027 GINT_TO_POINTER (buffer_format->italic&0x1));
2029 if (buffer_format->cs.color) {
2030 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2031 GINT_TO_POINTER (&(buffer_format->color)));
2033 if (buffer_format->cs.font_size) {
2034 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2035 GINT_TO_POINTER (buffer_format->font_size));
2037 if (buffer_format->cs.justification) {
2038 switch (buffer_format->justification) {
2039 case GTK_JUSTIFY_LEFT:
2040 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2041 GINT_TO_POINTER(TRUE));
2043 case GTK_JUSTIFY_CENTER:
2044 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2045 GINT_TO_POINTER(TRUE));
2047 case GTK_JUSTIFY_RIGHT:
2048 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2049 GINT_TO_POINTER(TRUE));
2056 if (buffer_format->cs.font) {
2057 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2058 GINT_TO_POINTER (buffer_format->font));
2060 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2061 if (buffer_format->cs.bullet) {
2062 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2063 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2065 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2067 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2069 g_free (buffer_format);
2070 g_free (current_format);
2072 /* Check dimming rules */
2073 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2074 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2078 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2080 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2082 ModestWindowPrivate *parent_priv;
2083 ModestMsgEditWindowPrivate *priv;
2085 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2088 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2089 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2090 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2091 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2093 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2094 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2095 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2098 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2100 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2101 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2103 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2104 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2106 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2107 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2110 switch (buffer_format->justification)
2112 case GTK_JUSTIFY_LEFT:
2113 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2115 case GTK_JUSTIFY_CENTER:
2116 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2118 case GTK_JUSTIFY_RIGHT:
2119 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2126 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2128 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2129 G_CALLBACK (modest_msg_edit_window_color_button_change),
2131 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2132 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2133 G_CALLBACK (modest_msg_edit_window_color_button_change),
2136 if (priv->current_size_index != buffer_format->font_size) {
2140 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2141 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2145 priv->current_size_index = buffer_format->font_size;
2147 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2148 markup = g_strconcat ("<span font_family='Sans'>",
2149 size_text, "</span>", NULL);
2151 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2155 gtk_tree_path_free (path);
2158 if (priv->current_face_index != buffer_format->font) {
2162 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2163 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2167 priv->current_face_index = buffer_format->font;
2168 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2169 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2170 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2177 g_free (buffer_format);
2181 #ifdef MODEST_HILDON_VERSION_0
2183 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2186 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2187 ModestMsgEditWindowPrivate *priv;
2188 GtkWidget *dialog = NULL;
2190 GdkColor *new_color = NULL;
2192 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2193 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2195 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2196 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2197 g_free (buffer_format);
2199 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2200 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2201 if (new_color != NULL) {
2202 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2203 (gpointer) new_color);
2206 gtk_widget_destroy (dialog);
2211 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2214 ModestMsgEditWindowPrivate *priv;
2215 GtkWidget *dialog = NULL;
2217 GdkColor *old_color = NULL;
2218 const GdkColor *new_color = NULL;
2220 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2221 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2223 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2224 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2226 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2227 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2228 if (new_color != NULL)
2229 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2231 gtk_widget_destroy (dialog);
2237 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2240 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2241 ModestMsgEditWindowPrivate *priv;
2242 GtkWidget *dialog = NULL;
2244 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2245 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2247 dialog = hildon_color_chooser_new ();
2248 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2249 g_free (buffer_format);
2251 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2253 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2254 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2257 gtk_widget_destroy (dialog);
2262 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2265 ModestMsgEditWindowPrivate *priv;
2266 GtkWidget *dialog = NULL;
2267 GdkColor *old_color = NULL;
2269 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2270 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2272 dialog = hildon_color_chooser_new ();
2273 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2275 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2277 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2278 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2280 gtk_widget_destroy (dialog);
2283 #endif /*!MODEST_HILDON_VERSION_0*/
2288 create_stream_for_uri (const gchar* uri)
2293 TnyStream *result = NULL;
2295 GnomeVFSHandle *handle = NULL;
2296 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2297 if (test == GNOME_VFS_OK) {
2298 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2299 /* Streams over OBEX (Bluetooth) are not seekable but
2300 * we expect them to be (we might need to read them
2301 * several times). So if this is a Bluetooth URI just
2302 * read the whole file into memory (this is not a fast
2303 * protocol so we can assume that these files are not
2304 * going to be very big) */
2305 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2306 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2307 TnyStream *memstream = tny_camel_mem_stream_new ();
2308 tny_stream_write_to_stream (vfssstream, memstream);
2309 g_object_unref (vfssstream);
2312 result = vfssstream;
2320 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2323 ModestMsgEditWindowPrivate *priv;
2324 GtkWidget *dialog = NULL;
2326 GSList *uris = NULL;
2327 GSList *uri_node = NULL;
2329 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2331 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2332 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2333 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2335 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2337 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2338 GTK_WINDOW (dialog), GTK_WINDOW (window));
2340 response = gtk_dialog_run (GTK_DIALOG (dialog));
2342 case GTK_RESPONSE_OK:
2344 gchar *current_folder;
2345 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2346 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2347 if (current_folder && current_folder != '\0') {
2349 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2350 current_folder, &err);
2352 g_debug ("Error storing latest used folder: %s", err->message);
2356 g_free (current_folder);
2362 gtk_widget_destroy (dialog);
2364 g_object_ref (window);
2365 /* The operation could take some time so allow the dialog to be closed */
2366 while (gtk_events_pending ())
2367 gtk_main_iteration ();
2369 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2371 GnomeVFSHandle *handle = NULL;
2372 GnomeVFSResult result;
2373 GtkTextIter position;
2374 GtkTextMark *insert_mark;
2376 uri = (const gchar *) uri_node->data;
2377 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2378 if (result == GNOME_VFS_OK) {
2380 GnomeVFSFileInfo *info;
2381 gchar *filename, *basename, *escaped_filename;
2382 TnyMimePart *mime_part;
2384 const gchar *mime_type = NULL;
2385 GnomeVFSURI *vfs_uri;
2386 guint64 stream_size;
2388 gnome_vfs_close (handle);
2389 vfs_uri = gnome_vfs_uri_new (uri);
2391 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2392 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2393 g_free (escaped_filename);
2394 gnome_vfs_uri_unref (vfs_uri);
2395 info = gnome_vfs_file_info_new ();
2397 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2398 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2400 mime_type = gnome_vfs_file_info_get_mime_type (info);
2402 mime_part = tny_platform_factory_new_mime_part
2403 (modest_runtime_get_platform_factory ());
2405 TnyStream *stream = create_stream_for_uri (uri);
2407 if (stream == NULL) {
2409 modest_platform_information_banner (NULL, NULL,
2410 _FM("sfil_ib_opening_not_allowed"));
2412 g_object_unref (mime_part);
2413 gnome_vfs_file_info_unref (info);
2417 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2419 content_id = g_strdup_printf ("%d", priv->next_cid);
2420 tny_mime_part_set_content_id (mime_part, content_id);
2421 g_free (content_id);
2424 basename = g_path_get_basename (filename);
2425 tny_mime_part_set_filename (mime_part, basename);
2428 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2430 if (pixbuf != NULL) {
2431 priv->images_size += stream_size;
2432 priv->images_count ++;
2433 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2434 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2435 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2436 tny_mime_part_get_content_id (mime_part), pixbuf);
2437 g_object_unref (pixbuf);
2439 tny_list_prepend (priv->images, (GObject *) mime_part);
2440 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2442 modest_platform_information_banner (NULL, NULL,
2443 _("mail_ib_file_operation_failed"));
2447 g_object_unref (mime_part);
2448 gnome_vfs_file_info_unref (info);
2452 g_object_unref (window);
2456 on_attach_file_response (GtkDialog *dialog,
2460 GSList *uris = NULL;
2462 GnomeVFSFileSize total_size, allowed_size;
2463 ModestMsgEditWindow *window;
2464 ModestMsgEditWindowPrivate *priv;
2469 case GTK_RESPONSE_OK:
2471 gchar *current_folder;
2473 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2474 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2475 if (current_folder && current_folder != '\0') {
2477 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2478 current_folder, &err);
2480 g_debug ("Error storing latest used folder: %s", err->message);
2484 g_free (current_folder);
2491 window = MODEST_MSG_EDIT_WINDOW (user_data);
2492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2494 /* allowed size is the maximum size - what's already there */
2495 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2496 &att_num, &att_size);
2497 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2500 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2502 const gchar *uri = (const gchar *) uri_node->data;
2505 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2507 if (total_size > allowed_size) {
2508 g_debug ("%s: total size: %u",
2509 __FUNCTION__, (unsigned int)total_size);
2512 allowed_size -= total_size;
2514 g_slist_foreach (uris, (GFunc) g_free, NULL);
2515 g_slist_free (uris);
2517 gtk_widget_destroy (GTK_WIDGET (dialog));
2521 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2523 GtkWidget *dialog = NULL;
2524 ModestMsgEditWindowPrivate *priv;
2527 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2531 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2534 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2535 GTK_FILE_CHOOSER_ACTION_OPEN);
2536 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2537 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2538 if (conf_folder && conf_folder[0] != '\0') {
2539 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2542 /* Set the default folder to images folder */
2543 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2544 ".documents", NULL);
2545 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2546 g_free (docs_folder);
2548 g_free (conf_folder);
2549 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2550 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2551 GTK_WINDOW (dialog), GTK_WINDOW (window));
2553 /* Connect to response & show */
2554 g_signal_connect (dialog, "response",
2555 G_CALLBACK (on_attach_file_response), window);
2556 gtk_widget_show (dialog);
2561 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2563 GnomeVFSFileSize allowed_size)
2566 GnomeVFSHandle *handle = NULL;
2567 ModestMsgEditWindowPrivate *priv;
2568 GnomeVFSResult result;
2569 GnomeVFSFileSize size = 0;
2570 g_return_val_if_fail (window, 0);
2571 g_return_val_if_fail (uri, 0);
2573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2575 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2576 if (result == GNOME_VFS_OK) {
2577 TnyMimePart *mime_part;
2579 const gchar *mime_type = NULL;
2581 gchar *escaped_filename;
2584 GnomeVFSFileInfo *info;
2585 GnomeVFSURI *vfs_uri;
2587 gnome_vfs_close (handle);
2588 vfs_uri = gnome_vfs_uri_new (uri);
2591 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2592 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2593 g_free (escaped_filename);
2594 gnome_vfs_uri_unref (vfs_uri);
2596 info = gnome_vfs_file_info_new ();
2598 if (gnome_vfs_get_file_info (uri,
2600 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2602 mime_type = gnome_vfs_file_info_get_mime_type (info);
2603 mime_part = tny_platform_factory_new_mime_part
2604 (modest_runtime_get_platform_factory ());
2606 /* try to get the attachment's size; this may fail for weird
2607 * file systems, like obex, upnp... */
2608 if (allowed_size != 0 &&
2609 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2611 if (size > allowed_size) {
2612 modest_platform_information_banner (NULL, NULL,
2613 _("mail_ib_error_attachment_size"));
2618 g_debug ("%s: could not get attachment size", __FUNCTION__);
2620 stream = create_stream_for_uri (uri);
2622 if (stream == NULL) {
2624 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2626 g_object_unref (mime_part);
2628 gnome_vfs_file_info_unref (info);
2632 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2633 g_object_unref (stream);
2635 content_id = g_strdup_printf ("%d", priv->next_cid);
2636 tny_mime_part_set_content_id (mime_part, content_id);
2637 g_free (content_id);
2640 basename = g_path_get_basename (filename);
2641 tny_mime_part_set_filename (mime_part, basename);
2644 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2645 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2647 info->size == 0, info->size);
2648 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2649 gtk_widget_show_all (priv->attachments_caption);
2650 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2652 g_object_unref (mime_part);
2653 gnome_vfs_file_info_unref (info);
2660 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2663 ModestMsgEditWindowPrivate *priv;
2666 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2669 if (att_list == NULL) {
2670 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2671 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2672 g_object_unref (att_list);
2676 g_object_ref (att_list);
2679 if (tny_list_get_length (att_list) == 0) {
2680 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2682 gboolean dialog_response;
2683 gchar *message = NULL;
2684 gchar *filename = NULL;
2686 if (tny_list_get_length (att_list) == 1) {
2688 iter = tny_list_create_iterator (att_list);
2689 part = (TnyMimePart *) tny_iterator_get_current (iter);
2690 g_object_unref (iter);
2691 if (TNY_IS_MSG (part)) {
2692 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2694 filename = tny_header_dup_subject (header);
2695 g_object_unref (header);
2697 if (filename == NULL) {
2698 filename = g_strdup (_("mail_va_no_subject"));
2701 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2703 g_object_unref (part);
2705 filename = g_strdup ("");
2707 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2708 "emev_nc_delete_attachments",
2709 tny_list_get_length (att_list)), filename);
2712 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2716 if (dialog_response != GTK_RESPONSE_OK) {
2717 g_object_unref (att_list);
2721 for (iter = tny_list_create_iterator (att_list);
2722 !tny_iterator_is_done (iter);
2723 tny_iterator_next (iter)) {
2724 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2725 const gchar *att_id;
2726 tny_list_remove (priv->attachments, (GObject *) mime_part);
2728 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2730 if (tny_list_get_length (priv->attachments) == 0)
2731 gtk_widget_hide (priv->attachments_caption);
2732 att_id = tny_mime_part_get_content_id (mime_part);
2734 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2736 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2737 g_object_unref (mime_part);
2739 g_object_unref (iter);
2742 g_object_unref (att_list);
2744 /* if the last attachment has been removed, focus the Subject: field */
2745 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2746 gtk_widget_grab_focus (priv->subject_field);
2750 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2753 ModestMsgEditWindowPrivate *priv;
2754 GdkColor *new_color;
2755 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2757 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2758 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2761 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2763 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2765 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2767 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2772 font_size_clicked (GtkToolButton *button,
2773 ModestMsgEditWindow *window)
2775 ModestMsgEditWindowPrivate *priv;
2776 GtkWidget *selector, *dialog;
2778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2780 selector = hildon_touch_selector_new ();
2781 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2782 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2784 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2785 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2786 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2788 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2792 WPTextBufferFormat format;
2794 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2796 memset (&format, 0, sizeof (format));
2797 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2799 format.cs.font_size = TRUE;
2800 format.cs.text_position = TRUE;
2801 format.cs.font = TRUE;
2802 format.font_size = new_index;
2803 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2805 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2806 GINT_TO_POINTER (new_index)))
2807 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2809 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2810 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2811 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2812 size_text, "</span>", NULL);
2814 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2818 gtk_widget_destroy (dialog);
2820 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2825 font_face_clicked (GtkToolButton *button,
2826 ModestMsgEditWindow *window)
2828 ModestMsgEditWindowPrivate *priv;
2829 GtkWidget *selector, *dialog;
2830 GtkCellRenderer *renderer;
2832 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2834 selector = hildon_touch_selector_new ();
2835 renderer = gtk_cell_renderer_text_new ();
2836 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2837 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2838 renderer, "family", 0, "text", 0, NULL);
2839 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2841 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2842 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2843 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2845 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2846 gint new_font_index;
2850 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2851 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2852 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2856 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2858 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2859 GINT_TO_POINTER(new_font_index)))
2860 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2862 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2863 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2865 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2869 gtk_tree_path_free (path);
2872 gtk_widget_destroy (dialog);
2874 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2879 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2882 ModestMsgEditWindowPrivate *priv = NULL;
2883 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2886 if (!priv->update_caption_visibility)
2889 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2891 gtk_widget_show (priv->cc_caption);
2893 gtk_widget_hide (priv->cc_caption);
2895 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2899 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2902 ModestMsgEditWindowPrivate *priv = NULL;
2903 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2906 if (!priv->update_caption_visibility)
2909 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2911 gtk_widget_show (priv->bcc_caption);
2913 gtk_widget_hide (priv->bcc_caption);
2915 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2919 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2920 ModestRecptEditor *editor)
2922 ModestMsgEditWindowPrivate *priv;
2924 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2925 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2927 /* we check for low-mem; in that case, show a warning, and don't allow
2928 * for the addressbook
2930 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2933 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2935 if (editor == NULL) {
2936 GtkWidget *view_focus, *parent;
2937 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2939 /* This code should be kept in sync with ModestRecptEditor. The
2940 textview inside the recpt editor is the one that really gets the
2941 focus. As it's inside a scrolled window, and this one inside the
2942 hbox recpt editor inherits from, we'll need to go up in the
2943 hierarchy to know if the text view is part of the recpt editor
2944 or if it's a different text entry */
2945 parent = gtk_widget_get_parent (view_focus);
2946 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2947 editor = MODEST_RECPT_EDITOR (parent);
2950 editor = MODEST_RECPT_EDITOR (priv->to_field);
2953 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2957 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2959 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2961 modest_msg_edit_window_open_addressbook (window, NULL);
2965 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2966 gboolean show_toolbar)
2968 ModestWindowPrivate *parent_priv;
2969 ModestMsgEditWindowPrivate *priv;
2971 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2972 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2973 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2975 /* We can not just use the code of
2976 modest_msg_edit_window_setup_toolbar because it has a
2977 mixture of both initialization and creation code. */
2979 gint current_format;
2980 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2981 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2982 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2983 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2985 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2988 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2993 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2994 TnyHeaderFlags priority_flags)
2996 ModestMsgEditWindowPrivate *priv;
2997 ModestWindowPrivate *parent_priv;
2999 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3001 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3002 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3004 if (priv->priority_flags != priority_flags) {
3005 GtkAction *priority_action = NULL;
3007 priv->priority_flags = priority_flags;
3009 switch (priority_flags) {
3010 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3011 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3012 MODEST_HEADER_ICON_HIGH,
3013 HILDON_ICON_SIZE_SMALL);
3014 gtk_widget_show (priv->priority_icon);
3015 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3016 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3018 case TNY_HEADER_FLAG_LOW_PRIORITY:
3019 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3020 MODEST_HEADER_ICON_LOW,
3021 HILDON_ICON_SIZE_SMALL);
3022 gtk_widget_show (priv->priority_icon);
3023 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3024 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3027 gtk_widget_hide (priv->priority_icon);
3028 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3029 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3032 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3033 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3035 gtk_widget_queue_resize (priv->subject_box);
3039 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3042 ModestMsgEditWindowPrivate *priv;
3043 ModestWindowPrivate *parent_priv;
3044 gint current_format;
3046 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3048 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3049 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3051 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3052 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3054 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3056 if (parent_priv->toolbar) {
3057 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3058 gtk_widget_hide (parent_priv->toolbar);
3060 gtk_widget_show (parent_priv->toolbar);
3064 if (current_format != file_format) {
3065 switch (file_format) {
3066 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3067 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3068 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3070 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3074 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3075 response = gtk_dialog_run (GTK_DIALOG (dialog));
3076 gtk_widget_destroy (dialog);
3077 if (response == GTK_RESPONSE_OK) {
3078 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3079 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3081 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3082 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3087 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3088 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3089 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3094 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3097 ModestMsgEditWindowPrivate *priv;
3098 WPTextBufferFormat oldfmt, fmt;
3099 gint old_position = 0;
3103 GdkColor *color = NULL;
3104 gboolean bold, bold_set, italic, italic_set;
3105 gboolean underline, underline_set;
3106 gboolean strikethrough, strikethrough_set;
3107 gboolean position_set;
3108 gboolean font_size_set, font_set, color_set;
3111 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3112 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3114 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3115 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3116 GTK_WINDOW(dialog), GTK_WINDOW (window));
3118 /* First we get the currently selected font information */
3119 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3121 switch (oldfmt.text_position) {
3122 case TEXT_POSITION_NORMAL:
3125 case TEXT_POSITION_SUPERSCRIPT:
3133 g_object_set (G_OBJECT (dialog),
3134 "bold", oldfmt.bold != FALSE,
3135 "bold-set", !oldfmt.cs.bold,
3136 "underline", oldfmt.underline != FALSE,
3137 "underline-set", !oldfmt.cs.underline,
3138 "italic", oldfmt.italic != FALSE,
3139 "italic-set", !oldfmt.cs.italic,
3140 "strikethrough", oldfmt.strikethrough != FALSE,
3141 "strikethrough-set", !oldfmt.cs.strikethrough,
3142 "color", &oldfmt.color,
3143 "color-set", !oldfmt.cs.color,
3144 "size", wp_font_size[oldfmt.font_size],
3145 "size-set", !oldfmt.cs.font_size,
3146 "position", old_position,
3147 "position-set", !oldfmt.cs.text_position,
3148 "family", wp_get_font_name (oldfmt.font),
3149 "family-set", !oldfmt.cs.font,
3152 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3153 GTK_WINDOW (dialog), GTK_WINDOW (window));
3154 gtk_widget_show_all (dialog);
3155 priv->font_dialog = dialog;
3156 response = gtk_dialog_run (GTK_DIALOG (dialog));
3157 priv->font_dialog = NULL;
3158 if (response == GTK_RESPONSE_OK) {
3160 g_object_get( dialog,
3162 "bold-set", &bold_set,
3163 "underline", &underline,
3164 "underline-set", &underline_set,
3166 "italic-set", &italic_set,
3167 "strikethrough", &strikethrough,
3168 "strikethrough-set", &strikethrough_set,
3170 "color-set", &color_set,
3172 "size-set", &font_size_set,
3173 "family", &font_name,
3174 "family-set", &font_set,
3175 "position", &position,
3176 "position-set", &position_set,
3181 if (response == GTK_RESPONSE_OK) {
3182 memset(&fmt, 0, sizeof(fmt));
3188 fmt.italic = italic;
3189 fmt.cs.italic = TRUE;
3191 if (underline_set) {
3192 fmt.underline = underline;
3193 fmt.cs.underline = TRUE;
3195 if (strikethrough_set) {
3196 fmt.strikethrough = strikethrough;
3197 fmt.cs.strikethrough = TRUE;
3202 ? TEXT_POSITION_NORMAL
3203 : ( ( position == 1 )
3204 ? TEXT_POSITION_SUPERSCRIPT
3205 : TEXT_POSITION_SUBSCRIPT );
3206 fmt.cs.text_position = TRUE;
3207 fmt.font_size = oldfmt.font_size;
3211 fmt.cs.color = TRUE;
3214 fmt.font = wp_get_font_index(font_name,
3219 if (font_size_set) {
3220 fmt.cs.font_size = TRUE;
3221 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3223 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3224 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3226 gtk_widget_destroy (dialog);
3228 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3232 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3234 ModestMsgEditWindowPrivate *priv;
3236 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3237 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3239 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3241 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3242 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3246 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3248 ModestMsgEditWindowPrivate *priv;
3250 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3251 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3253 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3255 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3256 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3261 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3263 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3265 priv->can_undo = can_undo;
3269 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3271 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3273 priv->can_redo = can_redo;
3277 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3279 ModestMsgEditWindowPrivate *priv;
3280 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3281 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3283 return priv->can_undo;
3287 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3289 ModestMsgEditWindowPrivate *priv;
3290 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3291 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3293 return priv->can_redo;
3298 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3301 GtkTextIter match_start, match_end;
3303 if (image_id == NULL)
3306 gtk_text_buffer_get_start_iter (buffer, &iter);
3308 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3309 GSList *tags = gtk_text_iter_get_tags (&match_start);
3311 for (node = tags; node != NULL; node = g_slist_next (node)) {
3312 GtkTextTag *tag = (GtkTextTag *) node->data;
3313 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3314 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3315 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3317 offset = gtk_text_iter_get_offset (&match_start);
3318 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3319 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3323 gtk_text_iter_forward_char (&iter);
3328 message_is_empty (ModestMsgEditWindow *window)
3330 ModestMsgEditWindowPrivate *priv = NULL;
3332 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3333 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3335 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3336 * so we can ignore markup.
3338 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3341 count = gtk_text_buffer_get_char_count (buf);
3347 msg_body_focus (GtkWidget *focus,
3348 GdkEventFocus *event,
3352 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3353 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3354 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3359 recpt_field_changed (GtkTextBuffer *buffer,
3360 ModestMsgEditWindow *editor)
3362 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3363 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3367 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3369 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3370 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3374 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3377 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3378 GtkTextBuffer *buffer;
3380 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3381 gtk_text_buffer_set_modified (buffer, modified);
3382 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3383 gtk_text_buffer_set_modified (buffer, modified);
3384 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3385 gtk_text_buffer_set_modified (buffer, modified);
3386 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3390 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3392 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3393 const char *account_name;
3394 GtkTextBuffer *buffer;
3396 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3397 if (gtk_text_buffer_get_modified (buffer))
3399 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3400 if (gtk_text_buffer_get_modified (buffer))
3402 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3403 if (gtk_text_buffer_get_modified (buffer))
3405 if (gtk_text_buffer_get_modified (priv->text_buffer))
3408 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3409 if (priv->original_mailbox) {
3410 if (!account_name || strcmp (account_name, priv->original_mailbox))
3412 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3423 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3425 ModestMsgEditWindowPrivate *priv = NULL;
3427 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3428 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3430 /* check if there's no recipient added */
3431 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3432 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3433 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3434 /* no recipient contents, then select contacts */
3435 modest_msg_edit_window_open_addressbook (window, NULL);
3439 g_object_ref (window);
3440 /* if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) { */
3441 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), NULL)) {
3442 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3443 g_object_unref (window);
3446 /* if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) { */
3447 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), NULL)) {
3448 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3449 g_object_unref (window);
3452 /* if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) { */
3453 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), NULL)) {
3454 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3455 g_object_unref (window);
3459 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3460 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3461 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3462 g_object_unref (window);
3469 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3470 ModestMsgEditWindow *window)
3472 modest_msg_edit_window_offer_attach_file (window);
3476 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3478 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3480 return priv->clipboard_text;
3484 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3486 ModestMsgEditWindow *window)
3488 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3489 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3492 /* It could happen that the window was already closed */
3493 if (!GTK_WIDGET_VISIBLE (window))
3496 g_object_ref (window);
3497 text = gtk_clipboard_wait_for_text (selection_clipboard);
3499 if (priv->clipboard_text != NULL) {
3500 g_free (priv->clipboard_text);
3502 priv->clipboard_text = text;
3504 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3506 g_object_unref (window);
3509 static gboolean clipboard_owner_change_idle (gpointer userdata)
3511 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3512 ModestMsgEditWindowPrivate *priv;
3514 gdk_threads_enter ();
3515 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3516 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3518 priv->clipboard_owner_idle = 0;
3519 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3520 gdk_threads_leave ();
3526 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3528 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3529 if (priv->clipboard_owner_idle == 0) {
3530 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3531 clipboard_owner_change_idle,
3532 g_object_ref (window),
3538 subject_field_move_cursor (GtkEntry *entry,
3539 GtkMovementStep step,
3544 /* It could happen that the window was already closed */
3545 if (!GTK_WIDGET_VISIBLE (window))
3548 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3552 update_window_title (ModestMsgEditWindow *window)
3554 ModestMsgEditWindowPrivate *priv = NULL;
3555 const gchar *subject;
3557 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3558 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3559 if (subject == NULL || subject[0] == '\0')
3560 subject = _("mail_va_new_email");
3562 gtk_window_set_title (GTK_WINDOW (window), subject);
3568 body_insert_text (GtkTextBuffer *buffer,
3569 GtkTextIter *location,
3572 ModestMsgEditWindow *window)
3574 GtkTextIter end_iter;
3581 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3583 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3585 offset = gtk_text_iter_get_offset (&end_iter);
3586 line = gtk_text_iter_get_line (&end_iter);
3590 while (text_offset < text + len) {
3591 if (*text_offset == '\n')
3593 if (text_lines + line >= MAX_BODY_LINES) {
3594 len = text_offset - text;
3600 utf8_len = g_utf8_strlen (text, len);
3602 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3603 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3604 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3609 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3611 /* Prevent endless recursion */
3612 result = g_strndup (text, utf8_end - text);
3613 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3614 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3615 (gpointer) result, (gpointer) (utf8_end - text),
3617 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3621 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3622 if (priv->max_chars_banner == NULL) {
3623 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3624 _CS("ckdg_ib_maximum_characters_reached"));
3625 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3631 subject_field_changed (GtkEditable *editable,
3632 ModestMsgEditWindow *window)
3634 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3635 update_window_title (window);
3636 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3637 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3638 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3641 subject_field_insert_text (GtkEditable *editable,
3643 gint new_text_length,
3645 ModestMsgEditWindow *window)
3647 GString *result = g_string_new ("");
3649 gint result_len = 0;
3650 const gchar *entry_text = NULL;
3653 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3654 old_length = g_utf8_strlen (entry_text, -1);
3656 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3657 gunichar c = g_utf8_get_char_validated (current, 8);
3658 /* Invalid unichar, stop */
3664 result = g_string_append_unichar (result, c);
3668 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3669 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3672 /* Prevent endless recursion */
3673 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3674 g_signal_emit_by_name (editable, "insert-text",
3675 (gpointer) result->str, (gpointer) result->len,
3676 (gpointer) position, (gpointer) window);
3677 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3681 if (result_len + old_length > 1000) {
3682 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3683 _CS("ckdg_ib_maximum_characters_reached"));
3685 g_string_free (result, TRUE);
3689 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3692 ModestMsgEditWindowPrivate *priv = NULL;
3694 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3695 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3697 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3700 gtk_widget_show_all (priv->find_toolbar);
3701 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3703 gtk_widget_hide_all (priv->find_toolbar);
3704 gtk_widget_grab_focus (priv->msg_body);
3709 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3711 GtkTextIter *match_start,
3712 GtkTextIter *match_end)
3714 GtkTextIter end_iter;
3715 gchar *str_casefold;
3718 gchar *range_casefold;
3721 gboolean result = FALSE;
3728 gtk_text_iter_forward_to_end (&end_iter);
3730 str_casefold = g_utf8_casefold (str, -1);
3731 str_chars_n = strlen (str);
3733 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3734 range_casefold = g_utf8_casefold (range_text, -1);
3735 range_chars_n = strlen (range_casefold);
3737 if (range_chars_n < str_chars_n) {
3738 g_free (str_casefold);
3739 g_free (range_text);
3740 g_free (range_casefold);
3744 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3745 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3746 if (!g_utf8_collate (range_subtext, str_casefold)) {
3747 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3749 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3750 match_start, match_end, NULL)) {
3751 g_debug ("Matched string with collate, but not matched in model");
3753 g_free (found_text);
3755 g_free (range_subtext);
3759 g_free (str_casefold);
3760 g_free (range_text);
3761 g_free (range_casefold);
3768 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3769 ModestMsgEditWindow *window)
3771 gchar *current_search = NULL;
3772 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3774 GtkTextIter selection_start, selection_end;
3775 GtkTextIter match_start, match_end;
3776 gboolean continue_search = FALSE;
3778 if (message_is_empty (window)) {
3779 g_free (priv->last_search);
3780 priv->last_search = NULL;
3781 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3785 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3786 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3787 g_free (current_search);
3788 g_free (priv->last_search);
3789 priv->last_search = NULL;
3790 /* Information banner about empty search */
3791 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3795 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3796 continue_search = TRUE;
3798 g_free (priv->last_search);
3799 priv->last_search = g_strdup (current_search);
3802 if (continue_search) {
3803 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3804 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3805 &match_start, &match_end);
3807 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3809 GtkTextIter buffer_start;
3810 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3811 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3812 &match_start, &match_end);
3814 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3817 /* Mark as selected the string found in search */
3819 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3820 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3821 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3823 g_free (priv->last_search);
3824 priv->last_search = NULL;
3826 g_free (current_search);
3830 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3832 ModestMsgEditWindowPrivate *priv;
3834 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3839 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3842 ModestMsgEditWindowPrivate *priv;
3844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3849 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3850 ModestMsgEditWindow *window)
3852 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3856 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3859 ModestMsgEditWindowPrivate *priv;
3860 TnyHeader *header = NULL;
3862 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3863 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3867 if (priv->draft_msg != NULL) {
3868 g_object_unref (priv->draft_msg);
3871 if (draft != NULL) {
3872 g_object_ref (draft);
3873 header = tny_msg_get_header (draft);
3874 if (priv->msg_uid) {
3875 g_free (priv->msg_uid);
3876 priv->msg_uid = NULL;
3878 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3881 priv->draft_msg = draft;
3885 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3886 GtkTextIter *start, GtkTextIter *end,
3889 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3890 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3893 if (tag == NULL) return;
3894 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3895 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3896 replace_with_images (window, priv->images);
3901 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3904 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3906 g_return_if_fail (TNY_IS_MIME_PART (part));
3907 tny_list_prepend (priv->attachments, (GObject *) part);
3908 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3909 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3910 gtk_widget_show_all (priv->attachments_caption);
3911 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3915 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3917 ModestMsgEditWindowPrivate *priv;
3919 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3920 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3922 return priv->msg_uid;
3926 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3927 ModestMsgEditWindowWidgetType widget_type)
3929 ModestMsgEditWindowPrivate *priv;
3931 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3934 switch (widget_type) {
3935 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3936 return priv->msg_body;
3938 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3939 return priv->to_field;
3941 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3942 return priv->cc_field;
3944 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3945 return priv->bcc_field;
3947 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3948 return priv->subject_field;
3950 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3951 return priv->attachments_view;
3959 remove_tags (WPTextBuffer *buffer)
3961 GtkTextIter start, end;
3963 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3964 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3966 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3970 on_account_removed (TnyAccountStore *account_store,
3971 TnyAccount *account,
3974 /* Do nothing if it's a store account, because we use the
3975 transport to send the messages */
3976 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3977 const gchar *parent_acc = NULL;
3978 const gchar *our_acc = NULL;
3980 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3981 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3982 /* Close this window if I'm showing a message of the removed account */
3983 if (strcmp (parent_acc, our_acc) == 0)
3984 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3989 update_signature (ModestMsgEditWindow *self,
3990 const gchar *old_account,
3991 const gchar *new_account)
3993 ModestMsgEditWindowPrivate *priv;
3994 gboolean has_old_signature, has_new_signature;
3996 ModestAccountMgr *mgr;
3999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4001 gtk_text_buffer_begin_user_action (priv->text_buffer);
4003 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4004 mgr = modest_runtime_get_account_mgr ();
4008 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4009 if (has_old_signature) {
4010 GtkTextIter match_start, match_end;
4012 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4013 seems that the search has some problems
4014 with the blank space at the end */
4015 if (gtk_text_iter_forward_search (&iter, "--",
4016 GTK_TEXT_SEARCH_TEXT_ONLY,
4017 &match_start, NULL, NULL)) {
4018 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4019 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4021 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4022 &match_start, &match_end, NULL)) {
4029 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4030 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4031 if (has_new_signature) {
4032 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4034 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4035 g_free (full_signature);
4038 gtk_text_buffer_end_user_action (priv->text_buffer);
4041 static void update_branding (ModestMsgEditWindow *self,
4042 const gchar *new_account)
4044 ModestMsgEditWindowPrivate *priv;
4045 ModestAccountMgr *mgr;
4046 const GdkPixbuf *new_icon = NULL;
4047 gchar *new_label = NULL;
4048 gboolean show = FALSE;
4050 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4052 mgr = modest_runtime_get_account_mgr ();
4054 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4056 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4057 gtk_widget_show (priv->brand_icon);
4060 gtk_widget_hide (priv->brand_icon);
4063 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4064 gtk_widget_show (priv->brand_label);
4068 gtk_widget_hide (priv->brand_label);
4072 gtk_widget_show (priv->brand_container);
4074 gtk_widget_hide (priv->brand_container);
4078 from_field_changed (HildonPickerButton *button,
4079 ModestMsgEditWindow *self)
4081 ModestMsgEditWindowPrivate *priv;
4082 gchar *old_account, *new_account;
4084 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4086 old_account = priv->last_from_account;
4087 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4090 g_warning ("%s, could not get the new account", __FUNCTION__);
4094 /* If the From is the same do nothing */
4095 if (old_account && new_account && !strcmp (old_account, new_account))
4098 priv->last_from_account = new_account;
4100 update_signature (self, old_account, new_account);
4101 update_branding (self, new_account);
4105 typedef struct _MessageSettingsHelper {
4106 ModestMsgEditWindow *window;
4107 GSList *priority_group;
4108 GSList *format_group;
4109 GtkToggleButton *current_priority;
4110 GtkToggleButton *current_format;
4111 } MessageSettingsHelper;
4114 on_priority_toggle (GtkToggleButton *button,
4115 MessageSettingsHelper *helper)
4118 ModestMsgEditWindowPrivate *priv;
4120 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4121 if (gtk_toggle_button_get_active (button)) {
4123 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4124 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4125 if ((node_button != button) &&
4126 gtk_toggle_button_get_active (node_button)) {
4127 gtk_toggle_button_set_active (node_button, FALSE);
4130 helper->current_priority = button;
4132 gboolean found = FALSE;
4133 /* If no one is active, activate it again */
4134 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4135 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4136 if (gtk_toggle_button_get_active (node_button)) {
4142 gtk_toggle_button_set_active (button, TRUE);
4148 on_format_toggle (GtkToggleButton *button,
4149 MessageSettingsHelper *helper)
4152 ModestMsgEditWindowPrivate *priv;
4154 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4155 if (gtk_toggle_button_get_active (button)) {
4157 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4158 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4159 if ((node_button != button) &&
4160 gtk_toggle_button_get_active (node_button)) {
4161 gtk_toggle_button_set_active (node_button, FALSE);
4164 helper->current_format = button;
4166 gboolean found = FALSE;
4167 /* If no one is active, activate it again */
4168 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4169 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4170 if (gtk_toggle_button_get_active (node_button)) {
4176 gtk_toggle_button_set_active (button, TRUE);
4183 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4188 GtkWidget *priority_hbox;
4189 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4190 GtkWidget *captioned;
4191 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4192 GtkWidget *format_hbox;
4193 GtkWidget *html_toggle, *text_toggle;
4194 ModestMsgEditWindowPrivate *priv;
4195 MessageSettingsHelper helper = {0,};
4197 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4198 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4199 helper.window = window;
4200 helper.priority_group = NULL;
4201 helper.format_group = NULL;
4203 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4204 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4206 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4207 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4208 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4209 vbox = gtk_vbox_new (FALSE, 0);
4210 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4211 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4212 gtk_container_add (GTK_CONTAINER (align), vbox);
4213 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4214 gtk_widget_show (align);
4215 gtk_widget_show (vbox);
4217 /* Priority toggles */
4218 priority_hbox = gtk_hbox_new (TRUE, 0);
4219 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4220 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4221 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4222 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4223 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4224 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4225 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4226 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4227 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4228 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4229 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4230 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4231 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4232 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4233 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4234 gtk_widget_show_all (priority_hbox);
4235 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4236 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4237 gtk_widget_show (captioned);
4238 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4240 /* format toggles */
4241 format_hbox = gtk_hbox_new (TRUE, 0);
4242 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4243 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4244 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4245 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4246 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4247 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4248 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4249 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4250 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4251 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4252 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4253 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4254 gtk_widget_show_all (format_hbox);
4255 gtk_widget_show (format_hbox);
4256 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4259 g_object_unref (title_sizegroup);
4260 g_object_unref (value_sizegroup);
4262 /* Set current values */
4263 switch (priv->priority_flags) {
4264 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4265 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4266 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4268 case TNY_HEADER_FLAG_LOW_PRIORITY:
4269 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4270 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4273 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4274 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4278 switch (modest_msg_edit_window_get_format (window)) {
4279 case MODEST_MSG_EDIT_FORMAT_TEXT:
4280 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4281 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4283 case MODEST_MSG_EDIT_FORMAT_HTML:
4285 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4286 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4290 /* Signal connects */
4291 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4292 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4293 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4294 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4295 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4297 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4298 GTK_WINDOW (dialog), GTK_WINDOW (window));
4300 /* Save settings if the user clicked on done */
4301 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4302 TnyHeaderFlags flags;
4303 ModestMsgEditFormat old_format, new_format;
4305 /* Set priority flags */
4306 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4307 if (priv->priority_flags != flags)
4308 modest_msg_edit_window_set_priority_flags (window, flags);
4310 /* Set edit format */
4311 old_format = modest_msg_edit_window_get_format (window);
4312 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4313 if (old_format != new_format) {
4314 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4315 modest_msg_edit_window_set_file_format (window, file_format);
4319 gtk_widget_destroy (dialog);
4320 g_slist_free (helper.priority_group);
4324 on_message_settings (GtkAction *action,
4325 ModestMsgEditWindow *window)
4327 modest_msg_edit_window_show_msg_settings_dialog (window);
4331 on_cc_button_toggled (HildonCheckButton *button,
4332 ModestMsgEditWindow *window)
4334 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4336 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4337 hildon_check_button_get_active (button));
4341 on_bcc_button_toggled (HildonCheckButton *button,
4342 ModestMsgEditWindow *window)
4344 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4346 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4347 hildon_check_button_get_active (button));
4351 setup_menu (ModestMsgEditWindow *self)
4353 ModestMsgEditWindowPrivate *priv = NULL;
4355 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4357 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4359 /* Settings menu buttons */
4360 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4361 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4363 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4364 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4365 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4367 priv->cc_button = hildon_check_button_new (0);
4368 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4369 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4371 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4373 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4374 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4375 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4376 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4378 priv->bcc_button = hildon_check_button_new (0);
4379 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4380 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4382 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4384 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4385 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4386 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4387 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4389 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4390 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4391 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4392 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4393 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4395 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4396 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4397 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4398 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4399 APP_MENU_CALLBACK (on_message_settings),
4401 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4402 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4407 emit_open_addressbook (GtkButton *button,
4408 ModestRecptEditor *editor)
4410 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4414 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4415 const gchar *label, GtkWidget *control)
4417 GtkWidget *abook_button;
4420 GtkWidget *label_widget;
4422 box = gtk_hbox_new (FALSE, 0);
4424 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4425 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4427 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4428 label_widget = gtk_label_new (label);
4429 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4430 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4432 gtk_container_add (GTK_CONTAINER (align), abook_button);
4433 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4434 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4435 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4436 if (title_size_group)
4437 gtk_size_group_add_widget (title_size_group, label_widget);
4438 if (value_size_group)
4439 gtk_size_group_add_widget (value_size_group, control);
4441 g_signal_connect (G_OBJECT (abook_button), "clicked",
4442 G_CALLBACK (emit_open_addressbook), control);
4448 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4450 ModestMsgEditWindowPrivate *priv = NULL;
4452 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4454 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4455 priv->max_chars_banner = NULL;