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 ();
978 hildon_gtk_widget_set_theme_size (priv->msg_body, MODEST_EDITABLE_SIZE);
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_ascii_strcasecmp (content_type, "multipart/related")) {
1253 parent = g_object_ref (msg);
1254 } else if (content_type && !g_ascii_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_ascii_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 (),
2538 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2539 if (conf_folder && conf_folder[0] != '\0') {
2540 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2543 /* Set the default folder to documents folder */
2544 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2547 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2548 ".documents", NULL);
2550 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2551 g_free (docs_folder);
2553 g_free (conf_folder);
2554 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2555 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2556 GTK_WINDOW (dialog), GTK_WINDOW (window));
2558 /* Connect to response & show */
2559 g_signal_connect (dialog, "response",
2560 G_CALLBACK (on_attach_file_response), window);
2561 gtk_widget_show (dialog);
2566 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2568 GnomeVFSFileSize allowed_size)
2571 GnomeVFSHandle *handle = NULL;
2572 ModestMsgEditWindowPrivate *priv;
2573 GnomeVFSResult result;
2574 GnomeVFSFileSize size = 0;
2575 g_return_val_if_fail (window, 0);
2576 g_return_val_if_fail (uri, 0);
2578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2580 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2581 if (result == GNOME_VFS_OK) {
2582 TnyMimePart *mime_part;
2584 const gchar *mime_type = NULL;
2586 gchar *escaped_filename;
2589 GnomeVFSFileInfo *info;
2590 GnomeVFSURI *vfs_uri;
2592 gnome_vfs_close (handle);
2593 vfs_uri = gnome_vfs_uri_new (uri);
2596 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2597 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2598 g_free (escaped_filename);
2599 gnome_vfs_uri_unref (vfs_uri);
2601 info = gnome_vfs_file_info_new ();
2603 if (gnome_vfs_get_file_info (uri,
2605 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2607 mime_type = gnome_vfs_file_info_get_mime_type (info);
2608 mime_part = tny_platform_factory_new_mime_part
2609 (modest_runtime_get_platform_factory ());
2611 /* try to get the attachment's size; this may fail for weird
2612 * file systems, like obex, upnp... */
2613 if (allowed_size != 0 &&
2614 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2616 if (size > allowed_size) {
2617 modest_platform_information_banner (NULL, NULL,
2618 _("mail_ib_error_attachment_size"));
2623 g_debug ("%s: could not get attachment size", __FUNCTION__);
2625 stream = create_stream_for_uri (uri);
2627 if (stream == NULL) {
2629 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2631 g_object_unref (mime_part);
2633 gnome_vfs_file_info_unref (info);
2637 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2638 g_object_unref (stream);
2640 content_id = g_strdup_printf ("%d", priv->next_cid);
2641 tny_mime_part_set_content_id (mime_part, content_id);
2642 g_free (content_id);
2645 basename = g_path_get_basename (filename);
2646 tny_mime_part_set_filename (mime_part, basename);
2649 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2650 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2652 info->size == 0, info->size);
2653 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2654 gtk_widget_show_all (priv->attachments_caption);
2655 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2657 g_object_unref (mime_part);
2658 gnome_vfs_file_info_unref (info);
2665 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2668 ModestMsgEditWindowPrivate *priv;
2671 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2672 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2674 if (att_list == NULL) {
2675 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2676 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2677 g_object_unref (att_list);
2681 g_object_ref (att_list);
2684 if (tny_list_get_length (att_list) == 0) {
2685 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2687 gboolean dialog_response;
2688 gchar *message = NULL;
2689 gchar *filename = NULL;
2691 if (tny_list_get_length (att_list) == 1) {
2693 iter = tny_list_create_iterator (att_list);
2694 part = (TnyMimePart *) tny_iterator_get_current (iter);
2695 g_object_unref (iter);
2696 if (TNY_IS_MSG (part)) {
2697 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2699 filename = tny_header_dup_subject (header);
2700 g_object_unref (header);
2702 if (filename == NULL) {
2703 filename = g_strdup (_("mail_va_no_subject"));
2706 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2708 g_object_unref (part);
2710 filename = g_strdup ("");
2712 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2713 "emev_nc_delete_attachments",
2714 tny_list_get_length (att_list)), filename);
2717 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2721 if (dialog_response != GTK_RESPONSE_OK) {
2722 g_object_unref (att_list);
2726 for (iter = tny_list_create_iterator (att_list);
2727 !tny_iterator_is_done (iter);
2728 tny_iterator_next (iter)) {
2729 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2730 const gchar *att_id;
2731 tny_list_remove (priv->attachments, (GObject *) mime_part);
2733 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2735 if (tny_list_get_length (priv->attachments) == 0)
2736 gtk_widget_hide (priv->attachments_caption);
2737 att_id = tny_mime_part_get_content_id (mime_part);
2739 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2741 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2742 g_object_unref (mime_part);
2744 g_object_unref (iter);
2747 g_object_unref (att_list);
2749 /* if the last attachment has been removed, focus the Subject: field */
2750 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2751 gtk_widget_grab_focus (priv->subject_field);
2755 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2758 ModestMsgEditWindowPrivate *priv;
2759 GdkColor *new_color;
2760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2762 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2763 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2766 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2768 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2770 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2772 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2777 font_size_clicked (GtkToolButton *button,
2778 ModestMsgEditWindow *window)
2780 ModestMsgEditWindowPrivate *priv;
2781 GtkWidget *selector, *dialog;
2783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2785 selector = hildon_touch_selector_new ();
2786 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2787 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2789 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2790 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2791 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2793 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2797 WPTextBufferFormat format;
2799 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2801 memset (&format, 0, sizeof (format));
2802 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2804 format.cs.font_size = TRUE;
2805 format.cs.text_position = TRUE;
2806 format.cs.font = TRUE;
2807 format.font_size = new_index;
2808 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2810 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2811 GINT_TO_POINTER (new_index)))
2812 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2814 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2815 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2816 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2817 size_text, "</span>", NULL);
2819 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2823 gtk_widget_destroy (dialog);
2825 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2830 font_face_clicked (GtkToolButton *button,
2831 ModestMsgEditWindow *window)
2833 ModestMsgEditWindowPrivate *priv;
2834 GtkWidget *selector, *dialog;
2835 GtkCellRenderer *renderer;
2837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2839 selector = hildon_touch_selector_new ();
2840 renderer = gtk_cell_renderer_text_new ();
2841 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2842 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2843 renderer, "family", 0, "text", 0, NULL);
2844 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2846 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2847 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2848 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2850 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2851 gint new_font_index;
2855 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2856 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2857 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2861 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2863 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2864 GINT_TO_POINTER(new_font_index)))
2865 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2867 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2868 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2870 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2874 gtk_tree_path_free (path);
2877 gtk_widget_destroy (dialog);
2879 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2884 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2887 ModestMsgEditWindowPrivate *priv = NULL;
2888 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2890 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2891 if (!priv->update_caption_visibility)
2894 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2896 gtk_widget_show (priv->cc_caption);
2898 gtk_widget_hide (priv->cc_caption);
2900 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2904 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2907 ModestMsgEditWindowPrivate *priv = NULL;
2908 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2910 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2911 if (!priv->update_caption_visibility)
2914 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2916 gtk_widget_show (priv->bcc_caption);
2918 gtk_widget_hide (priv->bcc_caption);
2920 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2924 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2925 ModestRecptEditor *editor)
2927 ModestMsgEditWindowPrivate *priv;
2929 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2930 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2932 /* we check for low-mem; in that case, show a warning, and don't allow
2933 * for the addressbook
2935 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2938 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2940 if (editor == NULL) {
2941 GtkWidget *view_focus, *parent;
2942 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2944 /* This code should be kept in sync with ModestRecptEditor. The
2945 textview inside the recpt editor is the one that really gets the
2946 focus. As it's inside a scrolled window, and this one inside the
2947 hbox recpt editor inherits from, we'll need to go up in the
2948 hierarchy to know if the text view is part of the recpt editor
2949 or if it's a different text entry */
2950 parent = gtk_widget_get_parent (view_focus);
2951 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2952 editor = MODEST_RECPT_EDITOR (parent);
2955 editor = MODEST_RECPT_EDITOR (priv->to_field);
2958 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2962 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2964 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2966 modest_msg_edit_window_open_addressbook (window, NULL);
2970 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2971 gboolean show_toolbar)
2973 ModestWindowPrivate *parent_priv;
2974 ModestMsgEditWindowPrivate *priv;
2976 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2977 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2978 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2980 /* We can not just use the code of
2981 modest_msg_edit_window_setup_toolbar because it has a
2982 mixture of both initialization and creation code. */
2984 gint current_format;
2985 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2986 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2987 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2988 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2990 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2993 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2998 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2999 TnyHeaderFlags priority_flags)
3001 ModestMsgEditWindowPrivate *priv;
3002 ModestWindowPrivate *parent_priv;
3004 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3006 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3007 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3009 if (priv->priority_flags != priority_flags) {
3010 GtkAction *priority_action = NULL;
3012 priv->priority_flags = priority_flags;
3014 switch (priority_flags) {
3015 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3016 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3017 MODEST_HEADER_ICON_HIGH,
3018 HILDON_ICON_SIZE_SMALL);
3019 gtk_widget_show (priv->priority_icon);
3020 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3021 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3023 case TNY_HEADER_FLAG_LOW_PRIORITY:
3024 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3025 MODEST_HEADER_ICON_LOW,
3026 HILDON_ICON_SIZE_SMALL);
3027 gtk_widget_show (priv->priority_icon);
3028 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3029 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3032 gtk_widget_hide (priv->priority_icon);
3033 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3034 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3037 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3038 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3040 gtk_widget_queue_resize (priv->subject_box);
3044 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3047 ModestMsgEditWindowPrivate *priv;
3048 ModestWindowPrivate *parent_priv;
3049 gint current_format;
3051 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3053 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3056 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3057 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3059 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3061 if (parent_priv->toolbar) {
3062 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3063 gtk_widget_hide (parent_priv->toolbar);
3065 gtk_widget_show (parent_priv->toolbar);
3069 if (current_format != file_format) {
3070 switch (file_format) {
3071 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3072 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3073 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3075 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3079 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3080 response = gtk_dialog_run (GTK_DIALOG (dialog));
3081 gtk_widget_destroy (dialog);
3082 if (response == GTK_RESPONSE_OK) {
3083 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3084 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3086 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3087 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3092 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3093 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3094 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3099 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3102 ModestMsgEditWindowPrivate *priv;
3103 WPTextBufferFormat oldfmt, fmt;
3104 gint old_position = 0;
3108 GdkColor *color = NULL;
3109 gboolean bold, bold_set, italic, italic_set;
3110 gboolean underline, underline_set;
3111 gboolean strikethrough, strikethrough_set;
3112 gboolean position_set;
3113 gboolean font_size_set, font_set, color_set;
3116 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3117 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3119 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3120 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3121 GTK_WINDOW(dialog), GTK_WINDOW (window));
3123 /* First we get the currently selected font information */
3124 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3126 switch (oldfmt.text_position) {
3127 case TEXT_POSITION_NORMAL:
3130 case TEXT_POSITION_SUPERSCRIPT:
3138 g_object_set (G_OBJECT (dialog),
3139 "bold", oldfmt.bold != FALSE,
3140 "bold-set", !oldfmt.cs.bold,
3141 "underline", oldfmt.underline != FALSE,
3142 "underline-set", !oldfmt.cs.underline,
3143 "italic", oldfmt.italic != FALSE,
3144 "italic-set", !oldfmt.cs.italic,
3145 "strikethrough", oldfmt.strikethrough != FALSE,
3146 "strikethrough-set", !oldfmt.cs.strikethrough,
3147 "color", &oldfmt.color,
3148 "color-set", !oldfmt.cs.color,
3149 "size", wp_font_size[oldfmt.font_size],
3150 "size-set", !oldfmt.cs.font_size,
3151 "position", old_position,
3152 "position-set", !oldfmt.cs.text_position,
3153 "family", wp_get_font_name (oldfmt.font),
3154 "family-set", !oldfmt.cs.font,
3157 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3158 GTK_WINDOW (dialog), GTK_WINDOW (window));
3159 gtk_widget_show_all (dialog);
3160 priv->font_dialog = dialog;
3161 response = gtk_dialog_run (GTK_DIALOG (dialog));
3162 priv->font_dialog = NULL;
3163 if (response == GTK_RESPONSE_OK) {
3165 g_object_get( dialog,
3167 "bold-set", &bold_set,
3168 "underline", &underline,
3169 "underline-set", &underline_set,
3171 "italic-set", &italic_set,
3172 "strikethrough", &strikethrough,
3173 "strikethrough-set", &strikethrough_set,
3175 "color-set", &color_set,
3177 "size-set", &font_size_set,
3178 "family", &font_name,
3179 "family-set", &font_set,
3180 "position", &position,
3181 "position-set", &position_set,
3186 if (response == GTK_RESPONSE_OK) {
3187 memset(&fmt, 0, sizeof(fmt));
3193 fmt.italic = italic;
3194 fmt.cs.italic = TRUE;
3196 if (underline_set) {
3197 fmt.underline = underline;
3198 fmt.cs.underline = TRUE;
3200 if (strikethrough_set) {
3201 fmt.strikethrough = strikethrough;
3202 fmt.cs.strikethrough = TRUE;
3207 ? TEXT_POSITION_NORMAL
3208 : ( ( position == 1 )
3209 ? TEXT_POSITION_SUPERSCRIPT
3210 : TEXT_POSITION_SUBSCRIPT );
3211 fmt.cs.text_position = TRUE;
3212 fmt.font_size = oldfmt.font_size;
3216 fmt.cs.color = TRUE;
3219 fmt.font = wp_get_font_index(font_name,
3224 if (font_size_set) {
3225 fmt.cs.font_size = TRUE;
3226 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3228 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3229 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3231 gtk_widget_destroy (dialog);
3233 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3237 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3239 ModestMsgEditWindowPrivate *priv;
3241 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3244 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3247 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3251 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3253 ModestMsgEditWindowPrivate *priv;
3255 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3260 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3261 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3266 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3268 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3270 priv->can_undo = can_undo;
3274 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3276 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3278 priv->can_redo = can_redo;
3282 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3284 ModestMsgEditWindowPrivate *priv;
3285 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3288 return priv->can_undo;
3292 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3294 ModestMsgEditWindowPrivate *priv;
3295 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3296 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3298 return priv->can_redo;
3303 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3306 GtkTextIter match_start, match_end;
3308 if (image_id == NULL)
3311 gtk_text_buffer_get_start_iter (buffer, &iter);
3313 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3314 GSList *tags = gtk_text_iter_get_tags (&match_start);
3316 for (node = tags; node != NULL; node = g_slist_next (node)) {
3317 GtkTextTag *tag = (GtkTextTag *) node->data;
3318 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3319 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3320 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3322 offset = gtk_text_iter_get_offset (&match_start);
3323 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3324 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3328 gtk_text_iter_forward_char (&iter);
3333 message_is_empty (ModestMsgEditWindow *window)
3335 ModestMsgEditWindowPrivate *priv = NULL;
3337 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3338 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3340 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3341 * so we can ignore markup.
3343 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3346 count = gtk_text_buffer_get_char_count (buf);
3352 msg_body_focus (GtkWidget *focus,
3353 GdkEventFocus *event,
3357 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3358 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3359 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3364 recpt_field_changed (GtkTextBuffer *buffer,
3365 ModestMsgEditWindow *editor)
3367 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3368 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3372 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3374 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3375 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3379 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3382 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3383 GtkTextBuffer *buffer;
3385 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3386 gtk_text_buffer_set_modified (buffer, modified);
3387 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3388 gtk_text_buffer_set_modified (buffer, modified);
3389 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3390 gtk_text_buffer_set_modified (buffer, modified);
3391 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3395 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3397 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3398 const char *account_name;
3399 GtkTextBuffer *buffer;
3401 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3402 if (gtk_text_buffer_get_modified (buffer))
3404 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3405 if (gtk_text_buffer_get_modified (buffer))
3407 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3408 if (gtk_text_buffer_get_modified (buffer))
3410 if (gtk_text_buffer_get_modified (priv->text_buffer))
3413 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3414 if (priv->original_mailbox) {
3415 if (!account_name || strcmp (account_name, priv->original_mailbox))
3417 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3428 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3430 ModestMsgEditWindowPrivate *priv = NULL;
3431 GSList *address_list = NULL;
3433 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3434 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3436 /* check if there's no recipient added */
3437 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3438 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3439 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3440 /* no recipient contents, then select contacts */
3441 modest_msg_edit_window_open_addressbook (window, NULL);
3446 g_object_ref (window);
3447 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3448 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3449 g_object_unref (window);
3452 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3453 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3454 g_object_unref (window);
3457 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3458 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3459 g_object_unref (window);
3463 /* Add contacts to address book */
3465 modest_address_book_add_address_list (address_list);
3467 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3468 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3469 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3470 g_object_unref (window);
3477 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3478 ModestMsgEditWindow *window)
3480 modest_msg_edit_window_offer_attach_file (window);
3484 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3486 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3488 return priv->clipboard_text;
3492 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3494 ModestMsgEditWindow *window)
3496 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3497 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3500 /* It could happen that the window was already closed */
3501 if (!GTK_WIDGET_VISIBLE (window))
3504 g_object_ref (window);
3505 text = gtk_clipboard_wait_for_text (selection_clipboard);
3507 if (priv->clipboard_text != NULL) {
3508 g_free (priv->clipboard_text);
3510 priv->clipboard_text = text;
3512 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3514 g_object_unref (window);
3517 static gboolean clipboard_owner_change_idle (gpointer userdata)
3519 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3520 ModestMsgEditWindowPrivate *priv;
3522 gdk_threads_enter ();
3523 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3524 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3526 priv->clipboard_owner_idle = 0;
3527 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3528 gdk_threads_leave ();
3534 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3536 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3537 if (priv->clipboard_owner_idle == 0) {
3538 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3539 clipboard_owner_change_idle,
3540 g_object_ref (window),
3546 subject_field_move_cursor (GtkEntry *entry,
3547 GtkMovementStep step,
3552 /* It could happen that the window was already closed */
3553 if (!GTK_WIDGET_VISIBLE (window))
3556 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3560 update_window_title (ModestMsgEditWindow *window)
3562 ModestMsgEditWindowPrivate *priv = NULL;
3563 const gchar *subject;
3565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3566 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3567 if (subject == NULL || subject[0] == '\0')
3568 subject = _("mail_va_new_email");
3570 gtk_window_set_title (GTK_WINDOW (window), subject);
3576 body_insert_text (GtkTextBuffer *buffer,
3577 GtkTextIter *location,
3580 ModestMsgEditWindow *window)
3582 GtkTextIter end_iter;
3589 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3591 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3593 offset = gtk_text_iter_get_offset (&end_iter);
3594 line = gtk_text_iter_get_line (&end_iter);
3598 while (text_offset < text + len) {
3599 if (*text_offset == '\n')
3601 if (text_lines + line >= MAX_BODY_LINES) {
3602 len = text_offset - text;
3608 utf8_len = g_utf8_strlen (text, len);
3610 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3611 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3612 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3617 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3619 /* Prevent endless recursion */
3620 result = g_strndup (text, utf8_end - text);
3621 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3622 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3623 (gpointer) result, (gpointer) (utf8_end - text),
3625 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3629 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3630 if (priv->max_chars_banner == NULL) {
3631 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3632 _CS("ckdg_ib_maximum_characters_reached"));
3633 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3639 subject_field_changed (GtkEditable *editable,
3640 ModestMsgEditWindow *window)
3642 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3643 update_window_title (window);
3644 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3645 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3646 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3649 subject_field_insert_text (GtkEditable *editable,
3651 gint new_text_length,
3653 ModestMsgEditWindow *window)
3655 GString *result = g_string_new ("");
3657 gint result_len = 0;
3658 const gchar *entry_text = NULL;
3661 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3662 old_length = g_utf8_strlen (entry_text, -1);
3664 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3665 gunichar c = g_utf8_get_char_validated (current, 8);
3666 /* Invalid unichar, stop */
3672 result = g_string_append_unichar (result, c);
3676 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3677 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3680 /* Prevent endless recursion */
3681 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3682 g_signal_emit_by_name (editable, "insert-text",
3683 (gpointer) result->str, (gpointer) result->len,
3684 (gpointer) position, (gpointer) window);
3685 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3689 if (result_len + old_length > 1000) {
3690 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3691 _CS("ckdg_ib_maximum_characters_reached"));
3693 g_string_free (result, TRUE);
3697 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3700 ModestMsgEditWindowPrivate *priv = NULL;
3702 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3703 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3705 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3708 gtk_widget_show_all (priv->find_toolbar);
3709 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3711 gtk_widget_hide_all (priv->find_toolbar);
3712 gtk_widget_grab_focus (priv->msg_body);
3717 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3719 GtkTextIter *match_start,
3720 GtkTextIter *match_end)
3722 GtkTextIter end_iter;
3723 gchar *str_casefold;
3726 gchar *range_casefold;
3729 gboolean result = FALSE;
3736 gtk_text_iter_forward_to_end (&end_iter);
3738 str_casefold = g_utf8_casefold (str, -1);
3739 str_chars_n = strlen (str);
3741 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3742 range_casefold = g_utf8_casefold (range_text, -1);
3743 range_chars_n = strlen (range_casefold);
3745 if (range_chars_n < str_chars_n) {
3746 g_free (str_casefold);
3747 g_free (range_text);
3748 g_free (range_casefold);
3752 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3753 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3754 if (!g_utf8_collate (range_subtext, str_casefold)) {
3755 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3757 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3758 match_start, match_end, NULL)) {
3759 g_debug ("Matched string with collate, but not matched in model");
3761 g_free (found_text);
3763 g_free (range_subtext);
3767 g_free (str_casefold);
3768 g_free (range_text);
3769 g_free (range_casefold);
3776 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3777 ModestMsgEditWindow *window)
3779 gchar *current_search = NULL;
3780 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3782 GtkTextIter selection_start, selection_end;
3783 GtkTextIter match_start, match_end;
3784 gboolean continue_search = FALSE;
3786 if (message_is_empty (window)) {
3787 g_free (priv->last_search);
3788 priv->last_search = NULL;
3789 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3793 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3794 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3795 g_free (current_search);
3796 g_free (priv->last_search);
3797 priv->last_search = NULL;
3798 /* Information banner about empty search */
3799 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3803 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3804 continue_search = TRUE;
3806 g_free (priv->last_search);
3807 priv->last_search = g_strdup (current_search);
3810 if (continue_search) {
3811 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3812 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3813 &match_start, &match_end);
3815 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3817 GtkTextIter buffer_start;
3818 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3819 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3820 &match_start, &match_end);
3822 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3825 /* Mark as selected the string found in search */
3827 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3828 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3829 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3831 g_free (priv->last_search);
3832 priv->last_search = NULL;
3834 g_free (current_search);
3838 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3840 ModestMsgEditWindowPrivate *priv;
3842 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3847 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3850 ModestMsgEditWindowPrivate *priv;
3852 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3857 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3858 ModestMsgEditWindow *window)
3860 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3864 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3867 ModestMsgEditWindowPrivate *priv;
3868 TnyHeader *header = NULL;
3870 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3871 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3873 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3875 if (priv->draft_msg != NULL) {
3876 g_object_unref (priv->draft_msg);
3879 if (draft != NULL) {
3880 g_object_ref (draft);
3881 header = tny_msg_get_header (draft);
3882 if (priv->msg_uid) {
3883 g_free (priv->msg_uid);
3884 priv->msg_uid = NULL;
3886 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3889 priv->draft_msg = draft;
3893 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3894 GtkTextIter *start, GtkTextIter *end,
3897 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3898 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3901 if (tag == NULL) return;
3902 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3903 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3904 replace_with_images (window, priv->images);
3909 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3912 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3914 g_return_if_fail (TNY_IS_MIME_PART (part));
3915 tny_list_prepend (priv->attachments, (GObject *) part);
3916 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3917 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3918 gtk_widget_show_all (priv->attachments_caption);
3919 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3923 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3925 ModestMsgEditWindowPrivate *priv;
3927 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3928 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3930 return priv->msg_uid;
3934 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3935 ModestMsgEditWindowWidgetType widget_type)
3937 ModestMsgEditWindowPrivate *priv;
3939 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3942 switch (widget_type) {
3943 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3944 return priv->msg_body;
3946 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3947 return priv->to_field;
3949 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3950 return priv->cc_field;
3952 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3953 return priv->bcc_field;
3955 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3956 return priv->subject_field;
3958 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3959 return priv->attachments_view;
3967 remove_tags (WPTextBuffer *buffer)
3969 GtkTextIter start, end;
3971 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3972 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3974 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3978 on_account_removed (TnyAccountStore *account_store,
3979 TnyAccount *account,
3982 /* Do nothing if it's a store account, because we use the
3983 transport to send the messages */
3984 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3985 const gchar *parent_acc = NULL;
3986 const gchar *our_acc = NULL;
3988 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3989 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3990 /* Close this window if I'm showing a message of the removed account */
3991 if (strcmp (parent_acc, our_acc) == 0)
3992 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3997 update_signature (ModestMsgEditWindow *self,
3998 const gchar *old_account,
3999 const gchar *new_account)
4001 ModestMsgEditWindowPrivate *priv;
4002 gboolean has_old_signature, has_new_signature;
4004 ModestAccountMgr *mgr;
4007 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4009 gtk_text_buffer_begin_user_action (priv->text_buffer);
4011 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4012 mgr = modest_runtime_get_account_mgr ();
4016 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4017 if (has_old_signature) {
4018 GtkTextIter match_start, match_end;
4020 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4021 seems that the search has some problems
4022 with the blank space at the end */
4023 if (gtk_text_iter_forward_search (&iter, "--",
4024 GTK_TEXT_SEARCH_TEXT_ONLY,
4025 &match_start, NULL, NULL)) {
4026 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4027 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4029 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4030 &match_start, &match_end, NULL)) {
4037 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4038 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4039 if (has_new_signature) {
4040 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4042 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4043 g_free (full_signature);
4046 gtk_text_buffer_end_user_action (priv->text_buffer);
4049 static void update_branding (ModestMsgEditWindow *self,
4050 const gchar *new_account)
4052 ModestMsgEditWindowPrivate *priv;
4053 ModestAccountMgr *mgr;
4054 const GdkPixbuf *new_icon = NULL;
4055 gchar *new_label = NULL;
4056 gboolean show = FALSE;
4058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4060 mgr = modest_runtime_get_account_mgr ();
4062 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4064 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4065 gtk_widget_show (priv->brand_icon);
4068 gtk_widget_hide (priv->brand_icon);
4071 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4072 gtk_widget_show (priv->brand_label);
4076 gtk_widget_hide (priv->brand_label);
4080 gtk_widget_show (priv->brand_container);
4082 gtk_widget_hide (priv->brand_container);
4086 from_field_changed (HildonPickerButton *button,
4087 ModestMsgEditWindow *self)
4089 ModestMsgEditWindowPrivate *priv;
4090 gchar *old_account, *new_account;
4092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4094 old_account = priv->last_from_account;
4095 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4098 g_warning ("%s, could not get the new account", __FUNCTION__);
4102 /* If the From is the same do nothing */
4103 if (old_account && new_account && !strcmp (old_account, new_account))
4106 priv->last_from_account = new_account;
4108 update_signature (self, old_account, new_account);
4109 update_branding (self, new_account);
4113 typedef struct _MessageSettingsHelper {
4114 ModestMsgEditWindow *window;
4115 GSList *priority_group;
4116 GSList *format_group;
4117 GtkToggleButton *current_priority;
4118 GtkToggleButton *current_format;
4119 } MessageSettingsHelper;
4122 on_priority_toggle (GtkToggleButton *button,
4123 MessageSettingsHelper *helper)
4126 ModestMsgEditWindowPrivate *priv;
4128 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4129 if (gtk_toggle_button_get_active (button)) {
4131 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4132 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4133 if ((node_button != button) &&
4134 gtk_toggle_button_get_active (node_button)) {
4135 gtk_toggle_button_set_active (node_button, FALSE);
4138 helper->current_priority = button;
4140 gboolean found = FALSE;
4141 /* If no one is active, activate it again */
4142 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4143 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4144 if (gtk_toggle_button_get_active (node_button)) {
4150 gtk_toggle_button_set_active (button, TRUE);
4156 on_format_toggle (GtkToggleButton *button,
4157 MessageSettingsHelper *helper)
4160 ModestMsgEditWindowPrivate *priv;
4162 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4163 if (gtk_toggle_button_get_active (button)) {
4165 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4166 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4167 if ((node_button != button) &&
4168 gtk_toggle_button_get_active (node_button)) {
4169 gtk_toggle_button_set_active (node_button, FALSE);
4172 helper->current_format = button;
4174 gboolean found = FALSE;
4175 /* If no one is active, activate it again */
4176 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4177 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4178 if (gtk_toggle_button_get_active (node_button)) {
4184 gtk_toggle_button_set_active (button, TRUE);
4191 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4196 GtkWidget *priority_hbox;
4197 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4198 GtkWidget *captioned;
4199 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4200 GtkWidget *format_hbox;
4201 GtkWidget *html_toggle, *text_toggle;
4202 ModestMsgEditWindowPrivate *priv;
4203 MessageSettingsHelper helper = {0,};
4205 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4206 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4207 helper.window = window;
4208 helper.priority_group = NULL;
4209 helper.format_group = NULL;
4211 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4212 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4214 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4215 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4216 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4217 vbox = gtk_vbox_new (FALSE, 0);
4218 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4219 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4220 gtk_container_add (GTK_CONTAINER (align), vbox);
4221 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4222 gtk_widget_show (align);
4223 gtk_widget_show (vbox);
4225 /* Priority toggles */
4226 priority_hbox = gtk_hbox_new (TRUE, 0);
4227 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4228 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4229 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4230 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4231 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4232 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4233 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4234 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4235 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4236 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4237 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4238 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4239 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4240 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4241 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4242 gtk_widget_show_all (priority_hbox);
4243 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4244 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4245 gtk_widget_show (captioned);
4246 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4248 /* format toggles */
4249 format_hbox = gtk_hbox_new (TRUE, 0);
4250 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4251 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4252 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4253 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4254 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4255 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4256 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4257 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4258 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4259 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4260 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4261 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4262 gtk_widget_show_all (format_hbox);
4263 gtk_widget_show (format_hbox);
4264 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4267 g_object_unref (title_sizegroup);
4268 g_object_unref (value_sizegroup);
4270 /* Set current values */
4271 switch (priv->priority_flags) {
4272 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4273 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4274 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4276 case TNY_HEADER_FLAG_LOW_PRIORITY:
4277 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4278 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4281 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4282 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4286 switch (modest_msg_edit_window_get_format (window)) {
4287 case MODEST_MSG_EDIT_FORMAT_TEXT:
4288 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4289 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4291 case MODEST_MSG_EDIT_FORMAT_HTML:
4293 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4294 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4298 /* Signal connects */
4299 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4300 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4301 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4302 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4303 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4305 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4306 GTK_WINDOW (dialog), GTK_WINDOW (window));
4308 /* Save settings if the user clicked on done */
4309 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4310 TnyHeaderFlags flags;
4311 ModestMsgEditFormat old_format, new_format;
4313 /* Set priority flags */
4314 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4315 if (priv->priority_flags != flags)
4316 modest_msg_edit_window_set_priority_flags (window, flags);
4318 /* Set edit format */
4319 old_format = modest_msg_edit_window_get_format (window);
4320 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4321 if (old_format != new_format) {
4322 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4323 modest_msg_edit_window_set_file_format (window, file_format);
4327 gtk_widget_destroy (dialog);
4328 g_slist_free (helper.priority_group);
4332 on_message_settings (GtkAction *action,
4333 ModestMsgEditWindow *window)
4335 modest_msg_edit_window_show_msg_settings_dialog (window);
4339 on_cc_button_toggled (HildonCheckButton *button,
4340 ModestMsgEditWindow *window)
4342 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4344 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4345 hildon_check_button_get_active (button));
4349 on_bcc_button_toggled (HildonCheckButton *button,
4350 ModestMsgEditWindow *window)
4352 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4354 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4355 hildon_check_button_get_active (button));
4359 setup_menu (ModestMsgEditWindow *self)
4361 ModestMsgEditWindowPrivate *priv = NULL;
4363 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4365 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4367 /* Settings menu buttons */
4368 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4369 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4371 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4372 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4373 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4375 priv->cc_button = hildon_check_button_new (0);
4376 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4377 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4379 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4381 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4382 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4383 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4384 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4386 priv->bcc_button = hildon_check_button_new (0);
4387 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4388 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4390 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4392 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4393 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4394 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4395 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4397 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4398 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4399 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4400 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4401 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4403 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4404 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4405 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4406 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4407 APP_MENU_CALLBACK (on_message_settings),
4409 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4410 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4415 emit_open_addressbook (GtkButton *button,
4416 ModestRecptEditor *editor)
4418 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4422 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4423 const gchar *label, GtkWidget *control)
4425 GtkWidget *abook_button;
4428 GtkWidget *label_widget;
4430 box = gtk_hbox_new (FALSE, 0);
4432 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4433 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4435 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4436 label_widget = gtk_label_new (label);
4437 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4438 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4440 gtk_container_add (GTK_CONTAINER (align), abook_button);
4441 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4442 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4443 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4444 if (title_size_group)
4445 gtk_size_group_add_widget (title_size_group, label_widget);
4446 if (value_size_group)
4447 gtk_size_group_add_widget (value_size_group, control);
4449 g_signal_connect (G_OBJECT (abook_button), "clicked",
4450 G_CALLBACK (emit_open_addressbook), control);
4456 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4458 ModestMsgEditWindowPrivate *priv = NULL;
4460 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4463 priv->max_chars_banner = NULL;