1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #include <libgnomevfs/gnome-vfs-mime.h>
75 #include <modest-utils.h>
76 #include "modest-maemo-utils.h"
77 #include <modest-ui-constants.h>
78 #include "modest-color-button.h"
80 #ifdef MODEST_USE_CALENDAR_WIDGETS
81 #include <calendar-ui-widgets.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 0
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
91 #define ATTACHMENT_BUTTON_WIDTH 118
92 #define MAX_FROM_VALUE 36
93 #define MAX_BODY_LENGTH 128*1024
94 #define MAX_BODY_LINES 2048
96 static gboolean is_wp_text_buffer_started = FALSE;
98 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
99 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
100 static void modest_msg_edit_window_finalize (GObject *obj);
102 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
103 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
104 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
107 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
108 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
109 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
110 GtkTextIter *start, GtkTextIter *end,
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void body_insert_text (GtkTextBuffer *buffer,
114 GtkTextIter *location,
117 ModestMsgEditWindow *window);
118 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
119 static void subject_field_insert_text (GtkEditable *editable,
121 gint new_text_length,
123 ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
128 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
129 ModestRecptEditor *editor);
130 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
131 ModestMsgEditWindow *window);
133 /* ModestWindow methods implementation */
134 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
135 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
136 gboolean show_toolbar);
137 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
139 ModestMsgEditWindow *window);
140 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
141 static void subject_field_move_cursor (GtkEntry *entry,
142 GtkMovementStep step,
146 static void update_window_title (ModestMsgEditWindow *window);
149 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
150 ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
155 GtkTextIter *match_start,
156 GtkTextIter *match_end);
158 static void remove_tags (WPTextBuffer *buffer);
160 static void on_account_removed (TnyAccountStore *account_store,
164 static void init_window (ModestMsgEditWindow *obj);
166 gboolean scroll_drag_timeout (gpointer userdata);
167 static void correct_scroll (ModestMsgEditWindow *w);
168 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
169 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void text_buffer_mark_set (GtkTextBuffer *buffer,
174 ModestMsgEditWindow *userdata);
175 static void on_message_settings (GtkAction *action,
176 ModestMsgEditWindow *window);
177 static void setup_menu (ModestMsgEditWindow *self);
179 static void from_field_changed (HildonPickerButton *button,
180 ModestMsgEditWindow *self);
181 static void font_size_clicked (GtkToolButton *button,
182 ModestMsgEditWindow *window);
183 static void font_face_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void update_signature (ModestMsgEditWindow *self,
186 const gchar *old_account,
187 const gchar *new_account);
188 static void update_branding (ModestMsgEditWindow *self,
189 const gchar *new_account);
190 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
191 const gchar *label, GtkWidget *control);
192 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
193 static void DEBUG_BUFFER (WPTextBuffer *buffer)
197 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
199 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
200 while (!gtk_text_iter_is_end (&iter)) {
201 GString *output = g_string_new ("");
202 GSList *toggled_tags;
205 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
206 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
207 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
208 GtkTextTag *tag = (GtkTextTag *) node->data;
210 g_object_get (G_OBJECT (tag), "name", &name, NULL);
211 output = g_string_append (output, name);
212 g_string_append (output, " ");
214 output = g_string_append (output, "] OPENED [ ");
215 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
216 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
217 GtkTextTag *tag = (GtkTextTag *) node->data;
219 g_object_get (G_OBJECT (tag), "name", &name, NULL);
220 output = g_string_append (output, name);
221 g_string_append (output, " ");
223 output = g_string_append (output, "]\n");
224 g_debug ("%s", output->str);
225 g_string_free (output, TRUE);
226 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
228 g_debug ("END BUFFER");
232 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
233 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
237 /* static gboolean */
238 /* on_key_pressed (GtkWidget *self, */
239 /* GdkEventKey *event, */
240 /* gpointer user_data); */
242 /* list my signals */
249 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
250 struct _ModestMsgEditWindowPrivate {
252 GtkWidget *header_box;
254 ModestPairList *from_field_protos;
255 GtkWidget *from_field;
256 gchar *last_from_account;
257 gchar *original_account_name;
262 gchar *original_mailbox;
266 GtkWidget *bcc_field;
267 GtkWidget *subject_field;
268 GtkWidget *attachments_view;
269 GtkWidget *priority_icon;
270 GtkWidget *subject_box;
271 GtkWidget *send_button;
273 GtkWidget *cc_caption;
274 GtkWidget *bcc_caption;
275 gboolean update_caption_visibility;
276 GtkWidget *attachments_caption;
278 GtkTextBuffer *text_buffer;
280 GtkWidget *font_size_toolitem;
281 GtkWidget *font_face_toolitem;
282 GtkWidget *font_color_button;
283 GtkWidget *font_color_toolitem;
284 GSList *font_items_group;
285 GtkTreeModel *faces_model;
286 gint current_face_index;
287 GtkWidget *font_tool_button_label;
288 GtkTreeModel *sizes_model;
289 gint current_size_index;
290 GtkWidget *size_tool_button_label;
292 GtkWidget *find_toolbar;
295 GtkWidget *font_dialog;
298 guint correct_scroll_idle;
299 guint scroll_drag_timeout_id;
303 TnyList *attachments;
308 TnyHeaderFlags priority_flags;
310 gboolean can_undo, can_redo;
311 gulong clipboard_change_handler_id;
312 gulong default_clipboard_change_handler_id;
313 gulong account_removed_handler_id;
314 guint clipboard_owner_idle;
315 gchar *clipboard_text;
324 GtkWidget *cc_button;
325 GtkWidget *bcc_button;
327 GtkWidget *max_chars_banner;
329 GtkWidget *brand_icon;
330 GtkWidget *brand_label;
331 GtkWidget *brand_container;
334 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
335 MODEST_TYPE_MSG_EDIT_WINDOW, \
336 ModestMsgEditWindowPrivate))
338 static GtkWindowClass *parent_class = NULL;
340 /* uncomment the following if you have defined any signals */
341 /* static guint signals[LAST_SIGNAL] = {0}; */
344 modest_msg_edit_window_get_type (void)
346 static GType my_type = 0;
348 static const GTypeInfo my_info = {
349 sizeof(ModestMsgEditWindowClass),
350 NULL, /* base init */
351 NULL, /* base finalize */
352 (GClassInitFunc) modest_msg_edit_window_class_init,
353 NULL, /* class finalize */
354 NULL, /* class data */
355 sizeof(ModestMsgEditWindow),
357 (GInstanceInitFunc) modest_msg_edit_window_init,
360 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
361 "ModestMsgEditWindow",
369 save_state (ModestWindow *self)
371 modest_widget_memory_save (modest_runtime_get_conf(),
372 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
377 restore_settings (ModestMsgEditWindow *self)
379 ModestConf *conf = NULL;
381 conf = modest_runtime_get_conf ();
383 /* Dim at start clipboard actions */
384 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
389 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
391 GObjectClass *gobject_class;
392 ModestWindowClass *modest_window_class;
393 gobject_class = (GObjectClass*) klass;
394 modest_window_class = (ModestWindowClass*) klass;
396 parent_class = g_type_class_peek_parent (klass);
397 gobject_class->finalize = modest_msg_edit_window_finalize;
399 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
400 modest_window_class->save_state_func = save_state;
401 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
403 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
407 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
409 ModestMsgEditWindowPrivate *priv;
410 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
412 priv->msg_body = NULL;
413 priv->from_field = NULL;
414 priv->to_field = NULL;
415 priv->cc_field = NULL;
416 priv->bcc_field = NULL;
417 priv->subject_field = NULL;
418 priv->attachments = TNY_LIST (tny_simple_list_new ());
419 priv->images = TNY_LIST (tny_simple_list_new ());
420 priv->images_size = 0;
421 priv->images_count = 0;
424 priv->cc_caption = NULL;
425 priv->bcc_caption = NULL;
426 priv->update_caption_visibility = FALSE;
428 priv->priority_flags = 0;
430 priv->find_toolbar = NULL;
431 priv->last_search = NULL;
433 priv->draft_msg = NULL;
434 priv->outbox_msg = NULL;
435 priv->msg_uid = NULL;
437 priv->can_undo = FALSE;
438 priv->can_redo = FALSE;
439 priv->clipboard_change_handler_id = 0;
440 priv->default_clipboard_change_handler_id = 0;
441 priv->account_removed_handler_id = 0;
442 priv->clipboard_owner_idle = 0;
443 priv->clipboard_text = NULL;
446 priv->scroll_drag_timeout_id = 0;
447 priv->correct_scroll_idle = 0;
448 priv->last_upper = 0.0;
450 priv->font_dialog = NULL;
451 priv->app_menu = NULL;
453 priv->references = NULL;
454 priv->in_reply_to = NULL;
455 priv->max_chars_banner = NULL;
457 if (!is_wp_text_buffer_started) {
458 is_wp_text_buffer_started = TRUE;
459 wp_text_buffer_library_init ();
464 hildon_program_add_window (hildon_program_get_instance(),
469 multimailbox_get_default_mailbox (const gchar *account_name)
471 gchar *transport_account;
472 gchar *result = NULL;
474 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
476 TNY_ACCOUNT_TYPE_TRANSPORT);
477 if (transport_account) {
479 ModestProtocolRegistry *registry;
481 registry = modest_runtime_get_protocol_registry ();
483 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
484 MODEST_ACCOUNT_PROTO, TRUE);
486 ModestProtocol *protocol =
487 modest_protocol_registry_get_protocol_by_name (registry,
488 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
490 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
491 ModestPairList *pair_list;
493 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
496 ModestPair *pair = (ModestPair *) pair_list->data;
497 result = g_strdup ((const gchar *) pair->first);
498 modest_pair_list_free (pair_list);
509 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
511 static ModestPairList*
512 get_transports (void)
514 GSList *transports = NULL;
516 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
517 GSList *accounts = modest_account_mgr_account_names (account_mgr,
518 TRUE /* only enabled accounts. */);
520 GSList *cursor = accounts;
522 gchar *account_name = cursor->data;
525 gchar *transport_account;
526 gboolean multi_mailbox = FALSE;
527 ModestProtocol *protocol = NULL;
529 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
531 transport_account = modest_account_mgr_get_server_account_name
532 (modest_runtime_get_account_mgr (),
534 TNY_ACCOUNT_TYPE_TRANSPORT);
535 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
536 ModestPairList *pair_list;
537 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
540 transports = g_slist_concat (transports, pair_list);
541 multi_mailbox = TRUE;
546 if (!multi_mailbox) {
547 gchar *from_string = NULL;
549 from_string = modest_account_mgr_get_from_string (account_mgr,
551 if (from_string && account_name) {
552 gchar *name = account_name;
553 ModestPair *pair = modest_pair_new ((gpointer) name,
554 (gpointer) from_string , TRUE);
555 transports = g_slist_prepend (transports, pair);
560 cursor = cursor->next;
562 g_slist_free (accounts); /* only free the accounts, not the elements,
563 * because they are used in the pairlist */
567 static void window_focus (GtkWindow *window,
571 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
575 scroll_drag_timeout (gpointer userdata)
577 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
578 ModestMsgEditWindowPrivate *priv;
580 /* It could happen that the window was already closed */
581 if (!GTK_WIDGET_VISIBLE (win))
584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
586 correct_scroll_without_drag_check (win, TRUE);
588 priv->scroll_drag_timeout_id = 0;
594 correct_scroll_without_drag_check_idle (gpointer userdata)
596 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
597 ModestMsgEditWindowPrivate *priv;
599 GdkRectangle rectangle;
600 gint offset_min, offset_max;
604 /* It could happen that the window was already closed */
605 if (!GTK_WIDGET_VISIBLE (w))
608 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
610 insert = gtk_text_buffer_get_insert (priv->text_buffer);
611 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
613 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
614 offset_min = priv->msg_body->allocation.y + rectangle.y;
615 offset_max = offset_min + rectangle.height;
617 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
618 offset_min = MAX (offset_min - 48, 0);
619 offset_max = MIN (offset_max + 48, vadj->upper);
621 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
623 priv->correct_scroll_idle = 0;
628 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
630 ModestMsgEditWindowPrivate *priv;
632 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
634 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
637 if (priv->correct_scroll_idle > 0) {
641 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
642 (GSourceFunc) correct_scroll_without_drag_check_idle,
648 correct_scroll (ModestMsgEditWindow *w)
650 ModestMsgEditWindowPrivate *priv;
652 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
653 if (gtk_grab_get_current () == priv->msg_body) {
654 if (priv->scroll_drag_timeout_id == 0) {
655 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
657 (GSourceFunc) scroll_drag_timeout,
664 correct_scroll_without_drag_check (w, TRUE);
668 text_buffer_end_user_action (GtkTextBuffer *buffer,
669 ModestMsgEditWindow *userdata)
672 correct_scroll (userdata);
676 text_buffer_mark_set (GtkTextBuffer *buffer,
679 ModestMsgEditWindow *userdata)
681 gtk_text_buffer_begin_user_action (buffer);
682 gtk_text_buffer_end_user_action (buffer);
686 cut_clipboard_check (GtkTextView *text_view,
689 GtkTextBuffer *buffer;
691 buffer = gtk_text_view_get_buffer (text_view);
692 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
693 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
698 copy_clipboard_check (GtkTextView *text_view,
701 GtkTextBuffer *buffer;
703 buffer = gtk_text_view_get_buffer (text_view);
704 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
705 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
710 attachment_deleted (ModestAttachmentsView *attachments_view,
713 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
718 body_size_request (GtkWidget *body,
722 /* Make sure the body always get at least 70 pixels */
723 if (req->height < 70)
728 connect_signals (ModestMsgEditWindow *obj)
730 ModestMsgEditWindowPrivate *priv;
732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
734 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
735 G_CALLBACK (text_buffer_refresh_attributes), obj);
736 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
737 G_CALLBACK (text_buffer_can_undo), obj);
738 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
739 G_CALLBACK (text_buffer_can_redo), obj);
740 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
741 G_CALLBACK (body_changed), obj);
742 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
743 G_CALLBACK (body_insert_text), obj);
744 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
745 G_CALLBACK (body_changed), obj);
746 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
747 G_CALLBACK (text_buffer_end_user_action), obj);
748 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
749 G_CALLBACK (text_buffer_mark_set), obj);
750 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
751 G_CALLBACK (text_buffer_apply_tag), obj);
752 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
753 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
754 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
755 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
756 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
757 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
759 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
760 G_CALLBACK (modest_ui_actions_on_send), obj);
762 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
763 G_CALLBACK (from_field_changed), obj);
765 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
766 G_CALLBACK (msg_body_focus), obj);
767 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
768 G_CALLBACK (msg_body_focus), obj);
769 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
770 G_CALLBACK (body_size_request), obj);
771 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
772 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
773 "changed", G_CALLBACK (recpt_field_changed), obj);
774 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
775 "changed", G_CALLBACK (recpt_field_changed), obj);
776 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
777 "changed", G_CALLBACK (recpt_field_changed), obj);
778 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
779 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
780 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
782 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
783 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
785 priv->clipboard_change_handler_id =
786 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
787 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
788 priv->default_clipboard_change_handler_id =
789 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
790 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
792 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
793 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
794 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
798 init_wp_text_view_style ()
800 static gboolean initialized = FALSE;
803 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
809 init_window (ModestMsgEditWindow *obj)
811 GtkWidget *to_caption, *subject_caption;
812 GtkWidget *main_vbox;
813 ModestMsgEditWindowPrivate *priv;
814 GtkActionGroup *action_group;
815 ModestWindowPrivate *parent_priv;
816 GdkPixbuf *window_icon = NULL;
817 GError *error = NULL;
819 GtkSizeGroup *title_size_group;
820 GtkSizeGroup *value_size_group;
821 GtkWidget *window_box;
822 GtkWidget *window_align;
823 #if (GTK_MINOR_VERSION >= 10)
824 GdkAtom deserialize_type;
826 GtkWidget *from_send_hbox;
827 GtkWidget *send_icon;
828 GtkWidget *attachments_label;
829 GtkWidget *branding_box;
831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
832 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
834 parent_priv->ui_manager = gtk_ui_manager_new();
835 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
836 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
838 /* Add common actions */
839 gtk_action_group_add_actions (action_group,
840 modest_msg_edit_action_entries,
841 G_N_ELEMENTS (modest_msg_edit_action_entries),
843 gtk_action_group_add_actions (action_group,
844 hildon2_msg_edit_action_entries,
845 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
847 gtk_action_group_add_toggle_actions (action_group,
848 modest_msg_edit_toggle_action_entries,
849 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
851 gtk_action_group_add_radio_actions (action_group,
852 modest_msg_edit_alignment_radio_action_entries,
853 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
855 G_CALLBACK (modest_ui_actions_on_change_justify),
857 gtk_action_group_add_radio_actions (action_group,
858 modest_msg_edit_priority_action_entries,
859 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
861 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
863 gtk_action_group_add_radio_actions (action_group,
864 modest_msg_edit_file_format_action_entries,
865 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
866 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
867 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
869 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
870 g_object_unref (action_group);
872 /* Load the UI definition */
873 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
876 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
877 g_clear_error (&error);
880 /* Add accelerators */
881 gtk_window_add_accel_group (GTK_WINDOW (obj),
882 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
884 parent_priv->menubar = NULL;
886 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
887 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
889 /* Note: This ModestPairList* must exist for as long as the picker
890 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
891 * so it can't know how to manage its memory. */
892 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
893 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
895 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
896 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
897 _("mail_va_from"), priv->from_field);
898 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
899 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
900 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
902 priv->to_field = modest_recpt_editor_new ();
903 priv->cc_field = modest_recpt_editor_new ();
904 priv->bcc_field = modest_recpt_editor_new ();
905 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
906 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
907 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
908 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
909 priv->priority_icon = gtk_image_new ();
910 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
911 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
912 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
913 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
914 hildon_entry_set_placeholder ((HildonEntry *) priv->subject_field, _("mail_va_no_subject"));
915 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
916 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
917 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
918 priv->attachments_view = modest_attachments_view_new (NULL);
919 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
920 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
922 priv->header_box = gtk_vbox_new (FALSE, 0);
924 to_caption = _create_addressbook_box
925 (title_size_group, value_size_group,
926 _("mail_va_to"), priv->to_field);
927 priv->cc_caption = _create_addressbook_box
928 (title_size_group, value_size_group,
929 _("mail_va_cc"), priv->cc_field);
930 priv->bcc_caption = _create_addressbook_box
931 (title_size_group, value_size_group,
932 _("mail_va_hotfix1"), priv->bcc_field);
933 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
934 _("mail_va_subject"), FALSE, priv->subject_box);
935 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
936 _("mail_va_attachment"),
938 priv->attachments_view,
939 HILDON_SIZE_AUTO_WIDTH |
940 HILDON_SIZE_AUTO_HEIGHT);
941 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
942 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
945 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
946 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
947 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
948 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
950 g_object_unref (title_size_group);
951 g_object_unref (value_size_group);
953 priv->brand_icon = gtk_image_new ();
954 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
955 priv->brand_label = gtk_label_new (NULL);
956 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
957 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
958 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
959 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
961 from_send_hbox = gtk_hbox_new (FALSE, 0);
962 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
963 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
965 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
966 gtk_widget_show (branding_box);
967 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
968 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
970 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
971 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
972 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
973 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
976 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
977 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
978 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
979 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
980 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
981 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
982 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
983 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
985 init_wp_text_view_style ();
987 priv->msg_body = modest_wp_text_view_new ();
990 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
991 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
992 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
993 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
994 #if (GTK_MINOR_VERSION >= 10)
995 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
996 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
998 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
999 deserialize_type, TRUE);
1001 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1003 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1004 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1006 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1008 priv->pannable = hildon_pannable_area_new ();
1010 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1012 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1013 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1014 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1016 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1017 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1018 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1020 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1021 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1023 window_box = gtk_vbox_new (FALSE, 0);
1024 gtk_container_add (GTK_CONTAINER(obj), window_box);
1026 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1028 /* Set window icon */
1029 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1031 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1032 g_object_unref (window_icon);
1037 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1039 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1041 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1042 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1043 priv->clipboard_change_handler_id))
1044 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1045 priv->clipboard_change_handler_id);
1046 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1047 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1048 priv->default_clipboard_change_handler_id))
1049 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1050 priv->default_clipboard_change_handler_id);
1052 if (priv->account_removed_handler_id &&
1053 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1054 priv->account_removed_handler_id))
1055 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1056 priv->account_removed_handler_id);
1060 modest_msg_edit_window_finalize (GObject *obj)
1062 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1064 if (priv->max_chars_banner) {
1065 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1066 priv->max_chars_banner = FALSE;
1069 /* Sanity check: shouldn't be needed, the window mgr should
1070 call this function before */
1071 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1073 if (priv->font_dialog != NULL) {
1074 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1077 if (priv->clipboard_text != NULL) {
1078 g_free (priv->clipboard_text);
1079 priv->clipboard_text = NULL;
1082 if (priv->draft_msg != NULL) {
1083 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1084 if (TNY_IS_HEADER (header)) {
1085 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1086 modest_window_mgr_unregister_header (mgr, header);
1088 g_object_unref (priv->draft_msg);
1089 priv->draft_msg = NULL;
1091 if (priv->outbox_msg != NULL) {
1092 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1093 if (TNY_IS_HEADER (header)) {
1094 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1095 modest_window_mgr_unregister_header (mgr, header);
1097 g_object_unref (priv->outbox_msg);
1098 priv->outbox_msg = NULL;
1100 if (priv->correct_scroll_idle > 0) {
1101 g_source_remove (priv->correct_scroll_idle);
1102 priv->correct_scroll_idle = 0;
1104 if (priv->scroll_drag_timeout_id > 0) {
1105 g_source_remove (priv->scroll_drag_timeout_id);
1106 priv->scroll_drag_timeout_id = 0;
1108 if (priv->clipboard_owner_idle > 0) {
1109 g_source_remove (priv->clipboard_owner_idle);
1110 priv->clipboard_owner_idle = 0;
1112 if (priv->original_account_name)
1113 g_free (priv->original_account_name);
1114 if (priv->original_mailbox)
1115 g_free (priv->original_mailbox);
1116 g_free (priv->msg_uid);
1117 g_free (priv->last_search);
1118 g_free (priv->references);
1119 g_free (priv->in_reply_to);
1120 g_object_unref (priv->attachments);
1121 g_object_unref (priv->images);
1123 /* This had to stay alive for as long as the picker that used it: */
1124 modest_pair_list_free (priv->from_field_protos);
1126 G_OBJECT_CLASS(parent_class)->finalize (obj);
1130 pixbuf_size_prepared (GdkPixbufLoader *loader,
1133 ModestMsgEditWindow *self)
1135 gint new_height, new_width;
1138 new_height = height;
1142 if (width > IMAGE_MAX_WIDTH) {
1143 new_height = height * IMAGE_MAX_WIDTH / width;
1144 new_width = IMAGE_MAX_WIDTH;
1147 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1151 pixbuf_from_stream (TnyStream *stream,
1152 const gchar *mime_type,
1153 guint64 *stream_size,
1154 ModestMsgEditWindow *self)
1156 GdkPixbufLoader *loader;
1159 GError *error = NULL;
1163 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1165 if (loader == NULL) {
1170 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1172 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1174 tny_stream_reset (TNY_STREAM (stream));
1175 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1176 unsigned char read_buffer[128];
1178 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1180 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1183 /* Allow some UI responsiveness */
1184 while (gtk_events_pending ())
1185 gtk_main_iteration ();
1187 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1189 gdk_pixbuf_loader_close (loader, &error);
1192 g_error_free (error);
1193 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1195 g_object_ref (pixbuf);
1196 g_object_unref (loader);
1201 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1202 GdkPixbuf *new_pixbuf;
1204 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1205 gdk_pixbuf_get_width (pixbuf);
1206 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1207 g_object_unref (pixbuf);
1208 pixbuf = new_pixbuf;
1212 *stream_size = size;
1218 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1220 ModestMsgEditWindowPrivate *priv;
1223 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1225 g_object_ref (self);
1226 for (iter = tny_list_create_iterator (attachments);
1227 !tny_iterator_is_done (iter);
1228 tny_iterator_next (iter)) {
1229 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1230 const gchar *cid = tny_mime_part_get_content_id (part);
1231 const gchar *mime_type = tny_mime_part_get_content_type (part);
1232 if ((cid != NULL)&&(mime_type != NULL)) {
1233 guint64 stream_size;
1234 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1235 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1238 g_object_unref (stream);
1240 if (pixbuf != NULL) {
1241 priv->images_count ++;
1242 priv->images_size += stream_size;
1243 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1244 g_object_unref (pixbuf);
1247 g_object_unref (part);
1249 g_object_unref (iter);
1250 g_object_unref (self);
1254 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1256 TnyMimePart *parent = NULL;
1257 const gchar *content_type = NULL;
1258 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1260 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1262 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1263 parent = g_object_ref (msg);
1264 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1265 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1268 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1269 iter = tny_list_create_iterator (parts);
1270 while (!tny_iterator_is_done (iter)) {
1272 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1273 content_type = tny_mime_part_get_content_type (part);
1274 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1278 g_object_unref (part);
1280 tny_iterator_next (iter);
1282 g_object_unref (iter);
1283 g_object_unref (parts);
1286 if (parent != NULL) {
1287 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1290 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1291 iter = tny_list_create_iterator (parts);
1292 while (!tny_iterator_is_done (iter)) {
1294 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1295 content_type = tny_mime_part_get_content_type (part);
1296 if (content_type && g_str_has_prefix (content_type, "image/")) {
1297 tny_list_prepend (priv->images, (GObject *) part);
1299 g_object_unref (part);
1300 tny_iterator_next (iter);
1302 g_object_unref (iter);
1303 g_object_unref (parts);
1304 g_object_unref (parent);
1309 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1312 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1314 for (iter = tny_list_create_iterator (attachments) ;
1315 !tny_iterator_is_done (iter);
1316 tny_iterator_next (iter)) {
1317 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1318 const gchar *cid = tny_mime_part_get_content_id (part);
1320 char *invalid = NULL;
1321 gint int_cid = strtol (cid, &invalid, 10);
1322 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1323 priv->next_cid = int_cid + 1;
1326 g_object_unref (part);
1328 g_object_unref (iter);
1332 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1335 gchar *to, *cc, *bcc, *subject;
1337 ModestMsgEditWindowPrivate *priv;
1338 ModestWindowPrivate *parent_priv;
1340 TnyHeaderFlags priority_flags;
1341 TnyFolder *msg_folder;
1342 gboolean is_html = FALSE;
1343 gboolean field_view_set;
1345 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1346 g_return_if_fail (TNY_IS_MSG (msg));
1348 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1349 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1351 header = tny_msg_get_header (msg);
1352 to = tny_header_dup_to (header);
1353 cc = tny_header_dup_cc (header);
1354 bcc = tny_header_dup_bcc (header);
1355 subject = tny_header_dup_subject (header);
1357 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1358 priority_flags = tny_header_get_priority (header);
1361 gchar *quoted_names = modest_text_utils_quote_names (to);
1362 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1363 g_free (quoted_names);
1366 field_view_set = TRUE;
1368 gchar *quoted_names = modest_text_utils_quote_names (cc);
1369 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1370 g_free (quoted_names);
1371 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1372 gtk_widget_show (priv->cc_caption);
1373 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1374 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1375 gtk_widget_hide (priv->cc_caption);
1376 field_view_set = FALSE;
1378 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1380 field_view_set = TRUE;
1382 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1383 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1384 g_free (quoted_names);
1385 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1386 gtk_widget_show (priv->bcc_caption);
1387 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1388 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1389 gtk_widget_hide (priv->bcc_caption);
1390 field_view_set = FALSE;
1392 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1396 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1397 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1400 update_window_title (self);
1402 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1403 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1405 if ((body == NULL)||(body[0] == '\0')) {
1407 body = modest_text_utils_convert_to_html ("");
1410 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1411 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1414 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1417 /* Add attachments to the view */
1418 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1419 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1420 if (tny_list_get_length (priv->attachments) == 0) {
1421 gtk_widget_hide (priv->attachments_caption);
1423 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1424 gtk_widget_show_all (priv->attachments_caption);
1426 get_related_images (self, msg);
1427 update_next_cid (self, priv->attachments);
1428 update_next_cid (self, priv->images);
1429 replace_with_images (self, priv->images);
1431 if (preserve_is_rich && !is_html) {
1432 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1433 /* Get the default format required from configuration */
1434 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1435 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1438 /* Set the default focus depending on having already a To: field or not */
1439 if ((!to)||(*to == '\0')) {
1440 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1442 gtk_widget_grab_focus (priv->msg_body);
1445 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1447 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1448 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1450 modest_msg_edit_window_set_modified (self, FALSE);
1452 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1453 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1454 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1455 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1457 if (priv->msg_uid) {
1458 g_free (priv->msg_uid);
1459 priv->msg_uid = NULL;
1462 /* we should set a reference to the incoming message if it is a draft */
1463 msg_folder = tny_msg_get_folder (msg);
1465 if (modest_tny_folder_is_local_folder (msg_folder)) {
1466 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1467 if (type == TNY_FOLDER_TYPE_INVALID)
1468 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1470 if (type == TNY_FOLDER_TYPE_DRAFTS)
1471 priv->draft_msg = g_object_ref(msg);
1472 if (type == TNY_FOLDER_TYPE_OUTBOX)
1473 priv->outbox_msg = g_object_ref(msg);
1474 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1476 g_object_unref (msg_folder);
1486 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1488 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1489 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1490 GtkWidget *placeholder;
1491 GtkWidget *tool_item;
1496 GtkWidget *sizes_menu;
1497 GtkWidget *fonts_menu;
1503 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1504 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1505 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1506 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1508 /* Font color placeholder */
1509 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1510 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1513 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1514 priv->font_color_button = modest_color_button_new ();
1515 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1516 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1517 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1518 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1519 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1520 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1521 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1522 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1524 G_CALLBACK (modest_msg_edit_window_color_button_change),
1527 /* Font size and face placeholder */
1528 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1529 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1531 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1532 priv->size_tool_button_label = gtk_label_new (NULL);
1533 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1534 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1535 size_text, "</span>", NULL);
1536 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1537 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1539 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1540 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1541 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1542 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1543 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1544 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1545 gtk_widget_set_sensitive (arrow, FALSE);
1546 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1547 sizes_menu = gtk_menu_new ();
1548 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1549 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1552 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1553 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1555 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1559 if (wp_font_size[size_index] == 12)
1560 priv->current_size_index = size_index;
1564 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1565 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1566 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1567 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1568 priv->font_size_toolitem = tool_item;
1571 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1572 priv->font_tool_button_label = gtk_label_new (NULL);
1573 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1574 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1575 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1577 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1578 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1579 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1580 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1581 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1582 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1583 gtk_widget_set_sensitive (arrow, FALSE);
1584 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1585 fonts_menu = gtk_menu_new ();
1586 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1587 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1590 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1592 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1593 0, wp_get_font_name (font_index),
1596 if (font_index == DEFAULT_FONT)
1597 priv->current_face_index = font_index;
1599 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1600 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1601 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1602 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1603 priv->font_face_toolitem = tool_item;
1605 /* Set expand and homogeneous for remaining items */
1606 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1607 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1608 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1609 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1610 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1611 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1613 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1614 will not show the tool items added to the placeholders) */
1615 gtk_widget_show_all (parent_priv->toolbar);
1617 /* Set the no show all *after* showing all items. We do not
1618 want the toolbar to be shown with a show all because it
1619 could go agains the gconf setting regarding showing or not
1620 the toolbar of the editor window */
1621 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1627 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1630 ModestWindowPrivate *parent_priv;
1631 ModestMsgEditWindowPrivate *priv;
1632 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1633 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1634 ModestWindowMgr *mgr = NULL;
1636 g_return_val_if_fail (msg, NULL);
1637 g_return_val_if_fail (account_name, NULL);
1639 mgr = modest_runtime_get_window_mgr ();
1641 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1643 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1644 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1646 /* Menubar. Update the state of some toggles */
1647 priv->from_field_protos = get_transports ();
1648 priv->original_mailbox = NULL;
1649 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1650 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 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1653 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1654 priv->original_mailbox = g_strdup (mailbox);
1655 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1656 /* We set the first mailbox as the active mailbox */
1657 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1658 if (priv->original_mailbox != NULL)
1659 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1660 (gpointer) priv->original_mailbox);
1662 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1663 (gpointer) account_name);
1665 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1667 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1668 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1669 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1671 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1672 hildon_touch_selector_get_current_text
1673 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1674 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1675 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1678 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1680 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1682 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1683 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1685 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1687 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1688 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1689 /* Add common dimming rules */
1690 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1691 modest_msg_edit_window_toolbar_dimming_entries,
1692 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1693 MODEST_WINDOW (obj));
1694 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1695 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1696 MODEST_WINDOW (obj));
1697 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1698 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1699 MODEST_WINDOW (obj));
1700 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1701 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1702 MODEST_WINDOW (obj));
1703 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1704 G_CALLBACK (modest_ui_dimming_rules_on_send),
1705 MODEST_WINDOW (obj));
1706 /* Insert dimming rules group for this window */
1707 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1708 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1710 /* Setup app menu */
1711 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1713 /* Checks the dimming rules */
1714 g_object_unref (toolbar_rules_group);
1715 g_object_unref (clipboard_rules_group);
1716 gtk_widget_hide (priv->priority_icon);
1717 gtk_widget_queue_resize (priv->subject_box);
1718 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1720 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1722 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1723 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1724 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1725 priv->update_caption_visibility = TRUE;
1727 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1729 /* Track account-removed signal, this window should be closed
1730 in the case we're creating a mail associated to the account
1732 priv->account_removed_handler_id =
1733 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1735 G_CALLBACK(on_account_removed),
1738 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1740 return (ModestWindow*) obj;
1744 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1746 GString **string_buffer = (GString **) user_data;
1748 *string_buffer = g_string_append (*string_buffer, buffer);
1754 * @result: A new string which should be freed with g_free().
1757 get_formatted_data (ModestMsgEditWindow *edit_window)
1759 ModestMsgEditWindowPrivate *priv;
1760 GString *string_buffer = g_string_new ("");
1762 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1764 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1766 modest_text_utils_hyperlinkify (string_buffer);
1768 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1770 return g_string_free (string_buffer, FALSE);
1775 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1778 const gchar *account_name;
1779 ModestMsgEditWindowPrivate *priv;
1780 TnyIterator *att_iter;
1781 const gchar *picker_active_id;
1783 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1785 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1787 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1788 g_return_val_if_fail (picker_active_id, NULL);
1789 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1791 /* don't free these (except from) */
1792 data = g_slice_new0 (MsgData);
1793 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1794 data->account_name = g_strdup (account_name);
1795 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1796 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1797 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1798 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1799 data->references = g_strdup (priv->references);
1800 data->in_reply_to = g_strdup (priv->in_reply_to);
1801 if (priv->draft_msg) {
1802 data->draft_msg = g_object_ref (priv->draft_msg);
1803 } else if (priv->outbox_msg) {
1804 data->draft_msg = g_object_ref (priv->outbox_msg);
1806 data->draft_msg = NULL;
1809 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1811 gtk_text_buffer_get_bounds (buf, &b, &e);
1812 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1814 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1815 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1817 data->html_body = NULL;
1819 /* deep-copy the data */
1820 att_iter = tny_list_create_iterator (priv->attachments);
1821 data->attachments = NULL;
1822 while (!tny_iterator_is_done (att_iter)) {
1823 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1824 if (!(TNY_IS_MIME_PART(part))) {
1825 g_warning ("strange data in attachment list");
1826 g_object_unref (part);
1827 tny_iterator_next (att_iter);
1830 data->attachments = g_list_append (data->attachments,
1832 tny_iterator_next (att_iter);
1834 g_object_unref (att_iter);
1836 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1837 att_iter = tny_list_create_iterator (priv->images);
1838 data->images = NULL;
1839 while (!tny_iterator_is_done (att_iter)) {
1840 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1842 if (!(TNY_IS_MIME_PART(part))) {
1843 g_warning ("strange data in attachment list");
1844 g_object_unref (part);
1845 tny_iterator_next (att_iter);
1848 cid = tny_mime_part_get_content_id (part);
1850 gchar *image_tag_id;
1851 GtkTextTag *image_tag;
1853 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1854 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1855 g_free (image_tag_id);
1857 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1859 ((gtk_text_iter_has_tag (&iter, image_tag))||
1860 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1861 data->images = g_list_append (data->images,
1862 g_object_ref (part));
1864 g_object_unref (part);
1865 tny_iterator_next (att_iter);
1867 g_object_unref (att_iter);
1869 data->priority_flags = priv->priority_flags;
1876 unref_gobject (GObject *obj, gpointer data)
1878 if (!G_IS_OBJECT(obj))
1880 g_object_unref (obj);
1884 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1887 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1895 g_free (data->from);
1896 g_free (data->subject);
1897 g_free (data->plain_body);
1898 g_free (data->html_body);
1899 g_free (data->account_name);
1900 g_free (data->references);
1901 g_free (data->in_reply_to);
1903 if (data->draft_msg != NULL) {
1904 g_object_unref (data->draft_msg);
1905 data->draft_msg = NULL;
1908 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1909 g_list_free (data->attachments);
1910 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1911 g_list_free (data->images);
1913 g_slice_free (MsgData, data);
1917 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1919 guint64 *parts_size)
1921 ModestMsgEditWindowPrivate *priv;
1923 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1925 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1927 /* TODO: add images */
1928 *parts_size += priv->images_size;
1929 *parts_count += priv->images_count;
1934 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1937 ModestMsgEditWindowPrivate *priv = NULL;
1938 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1942 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1944 return MODEST_MSG_EDIT_FORMAT_HTML;
1946 return MODEST_MSG_EDIT_FORMAT_TEXT;
1950 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1951 ModestMsgEditFormat format)
1953 ModestMsgEditWindowPrivate *priv;
1954 ModestWindowPrivate *parent_priv;
1956 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1958 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1961 case MODEST_MSG_EDIT_FORMAT_HTML:
1962 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1963 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1965 case MODEST_MSG_EDIT_FORMAT_TEXT:
1966 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1967 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1970 g_return_if_reached ();
1974 ModestMsgEditFormatState *
1975 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1977 ModestMsgEditFormatState *format_state = NULL;
1978 ModestMsgEditWindowPrivate *priv;
1979 WPTextBufferFormat *buffer_format;
1981 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1983 buffer_format = g_new0 (WPTextBufferFormat, 1);
1984 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1986 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1988 format_state = g_new0 (ModestMsgEditFormatState, 1);
1989 format_state->bold = buffer_format->bold&0x1;
1990 format_state->italics = buffer_format->italic&0x1;
1991 format_state->bullet = buffer_format->bullet&0x1;
1992 format_state->color = buffer_format->color;
1993 format_state->font_size = buffer_format->font_size;
1994 format_state->font_family = wp_get_font_name (buffer_format->font);
1995 format_state->justification = buffer_format->justification;
1996 g_free (buffer_format);
1998 return format_state;
2003 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2004 const ModestMsgEditFormatState *format_state)
2006 ModestMsgEditWindowPrivate *priv;
2007 WPTextBufferFormat *buffer_format;
2008 WPTextBufferFormat *current_format;
2010 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2011 g_return_if_fail (format_state != NULL);
2013 buffer_format = g_new0 (WPTextBufferFormat, 1);
2014 current_format = g_new0 (WPTextBufferFormat, 1);
2016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2017 gtk_widget_grab_focus (priv->msg_body);
2018 buffer_format->bold = (format_state->bold != FALSE);
2019 buffer_format->italic = (format_state->italics != FALSE);
2020 buffer_format->color = format_state->color;
2021 buffer_format->font_size = format_state->font_size;
2022 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2023 buffer_format->justification = format_state->justification;
2024 buffer_format->bullet = format_state->bullet;
2026 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2028 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2029 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2030 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2031 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2032 buffer_format->cs.font = (buffer_format->font != current_format->font);
2033 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2034 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2036 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2037 if (buffer_format->cs.bold) {
2038 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2039 GINT_TO_POINTER (buffer_format->bold&0x1));
2041 if (buffer_format->cs.italic) {
2042 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2043 GINT_TO_POINTER (buffer_format->italic&0x1));
2045 if (buffer_format->cs.color) {
2046 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2047 GINT_TO_POINTER (&(buffer_format->color)));
2049 if (buffer_format->cs.font_size) {
2050 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2051 GINT_TO_POINTER (buffer_format->font_size));
2053 if (buffer_format->cs.justification) {
2054 switch (buffer_format->justification) {
2055 case GTK_JUSTIFY_LEFT:
2056 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2057 GINT_TO_POINTER(TRUE));
2059 case GTK_JUSTIFY_CENTER:
2060 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2061 GINT_TO_POINTER(TRUE));
2063 case GTK_JUSTIFY_RIGHT:
2064 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2065 GINT_TO_POINTER(TRUE));
2072 if (buffer_format->cs.font) {
2073 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2074 GINT_TO_POINTER (buffer_format->font));
2076 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2077 if (buffer_format->cs.bullet) {
2078 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2079 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2081 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2083 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2085 g_free (buffer_format);
2086 g_free (current_format);
2088 /* Check dimming rules */
2089 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2090 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2094 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2096 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2098 ModestWindowPrivate *parent_priv;
2099 ModestMsgEditWindowPrivate *priv;
2101 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2102 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2104 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2105 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2106 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2107 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2109 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2110 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2111 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2114 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2116 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2117 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2119 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2120 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2122 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2123 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2126 switch (buffer_format->justification)
2128 case GTK_JUSTIFY_LEFT:
2129 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2131 case GTK_JUSTIFY_CENTER:
2132 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2134 case GTK_JUSTIFY_RIGHT:
2135 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2142 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2144 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2145 G_CALLBACK (modest_msg_edit_window_color_button_change),
2147 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2148 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2149 G_CALLBACK (modest_msg_edit_window_color_button_change),
2152 if (priv->current_size_index != buffer_format->font_size) {
2156 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2157 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2161 priv->current_size_index = buffer_format->font_size;
2163 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2164 markup = g_strconcat ("<span font_family='Sans'>",
2165 size_text, "</span>", NULL);
2167 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2171 gtk_tree_path_free (path);
2174 if (priv->current_face_index != buffer_format->font) {
2178 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2179 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2183 priv->current_face_index = buffer_format->font;
2184 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2185 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2186 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2193 g_free (buffer_format);
2199 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2201 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2202 ModestMsgEditWindowPrivate *priv;
2203 GtkWidget *dialog = NULL;
2205 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2206 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2208 dialog = hildon_color_chooser_new ();
2209 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2210 g_free (buffer_format);
2212 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2214 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2215 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2218 gtk_widget_destroy (dialog);
2223 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2225 ModestMsgEditWindowPrivate *priv;
2226 GtkWidget *dialog = NULL;
2227 GdkColor *old_color = NULL;
2229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2230 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2232 dialog = hildon_color_chooser_new ();
2233 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2235 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2237 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2238 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2240 gtk_widget_destroy (dialog);
2245 create_stream_for_uri (const gchar* uri)
2250 TnyStream *result = NULL;
2252 GnomeVFSHandle *handle = NULL;
2253 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2254 if (test == GNOME_VFS_OK) {
2255 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2256 /* Streams over OBEX (Bluetooth) are not seekable but
2257 * we expect them to be (we might need to read them
2258 * several times). So if this is a Bluetooth URI just
2259 * read the whole file into memory (this is not a fast
2260 * protocol so we can assume that these files are not
2261 * going to be very big) */
2262 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2263 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2264 TnyStream *memstream = tny_camel_mem_stream_new ();
2265 tny_stream_write_to_stream (vfssstream, memstream);
2266 g_object_unref (vfssstream);
2269 result = vfssstream;
2277 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2280 ModestMsgEditWindowPrivate *priv;
2281 GtkWidget *dialog = NULL;
2283 GSList *uris = NULL;
2284 GSList *uri_node = NULL;
2286 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2289 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2290 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2292 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2294 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2295 GTK_WINDOW (dialog), GTK_WINDOW (window));
2297 response = gtk_dialog_run (GTK_DIALOG (dialog));
2299 case GTK_RESPONSE_OK:
2301 gchar *current_folder;
2302 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2303 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2304 if (current_folder && current_folder != '\0') {
2306 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2307 current_folder, &err);
2309 g_debug ("Error storing latest used folder: %s", err->message);
2313 g_free (current_folder);
2319 gtk_widget_destroy (dialog);
2321 g_object_ref (window);
2322 /* The operation could take some time so allow the dialog to be closed */
2323 while (gtk_events_pending ())
2324 gtk_main_iteration ();
2326 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2328 GnomeVFSHandle *handle = NULL;
2329 GnomeVFSResult result;
2330 GtkTextIter position;
2331 GtkTextMark *insert_mark;
2333 uri = (const gchar *) uri_node->data;
2334 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2335 if (result == GNOME_VFS_OK) {
2337 GnomeVFSFileInfo *info;
2338 gchar *filename, *basename, *escaped_filename;
2339 TnyMimePart *mime_part;
2341 const gchar *mime_type = NULL;
2342 GnomeVFSURI *vfs_uri;
2343 guint64 stream_size;
2345 gnome_vfs_close (handle);
2346 vfs_uri = gnome_vfs_uri_new (uri);
2348 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2349 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2350 g_free (escaped_filename);
2351 gnome_vfs_uri_unref (vfs_uri);
2352 info = gnome_vfs_file_info_new ();
2354 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2355 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2357 mime_type = gnome_vfs_file_info_get_mime_type (info);
2359 mime_part = tny_platform_factory_new_mime_part
2360 (modest_runtime_get_platform_factory ());
2362 TnyStream *stream = create_stream_for_uri (uri);
2364 if (stream == NULL) {
2366 modest_platform_information_banner (NULL, NULL,
2367 _FM("sfil_ib_opening_not_allowed"));
2369 g_object_unref (mime_part);
2370 gnome_vfs_file_info_unref (info);
2374 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2376 content_id = g_strdup_printf ("%d", priv->next_cid);
2377 tny_mime_part_set_content_id (mime_part, content_id);
2378 g_free (content_id);
2381 basename = g_path_get_basename (filename);
2382 tny_mime_part_set_filename (mime_part, basename);
2385 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2387 if (pixbuf != NULL) {
2388 priv->images_size += stream_size;
2389 priv->images_count ++;
2390 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2391 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2392 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2393 tny_mime_part_get_content_id (mime_part), pixbuf);
2394 g_object_unref (pixbuf);
2396 tny_list_prepend (priv->images, (GObject *) mime_part);
2397 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2399 modest_platform_information_banner (NULL, NULL,
2400 _("mail_ib_file_operation_failed"));
2404 g_object_unref (mime_part);
2405 gnome_vfs_file_info_unref (info);
2409 g_object_unref (window);
2413 on_attach_file_response (GtkDialog *dialog,
2417 GSList *uris = NULL;
2419 GnomeVFSFileSize total_size, allowed_size;
2420 ModestMsgEditWindow *window;
2421 ModestMsgEditWindowPrivate *priv;
2426 case GTK_RESPONSE_OK:
2428 gchar *current_folder;
2430 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2431 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2432 if (current_folder && current_folder != '\0') {
2434 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2435 current_folder, &err);
2437 g_debug ("Error storing latest used folder: %s", err->message);
2441 g_free (current_folder);
2448 window = MODEST_MSG_EDIT_WINDOW (user_data);
2449 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2451 /* allowed size is the maximum size - what's already there */
2452 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2453 &att_num, &att_size);
2454 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2457 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2459 const gchar *uri = (const gchar *) uri_node->data;
2462 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2464 if (total_size > allowed_size) {
2465 g_debug ("%s: total size: %u",
2466 __FUNCTION__, (unsigned int)total_size);
2469 allowed_size -= total_size;
2471 g_slist_foreach (uris, (GFunc) g_free, NULL);
2472 g_slist_free (uris);
2474 gtk_widget_destroy (GTK_WIDGET (dialog));
2478 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2480 GtkWidget *dialog = NULL;
2481 ModestMsgEditWindowPrivate *priv;
2484 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2488 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2491 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2492 GTK_FILE_CHOOSER_ACTION_OPEN);
2493 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2494 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2495 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2496 if (conf_folder && conf_folder[0] != '\0') {
2497 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2500 /* Set the default folder to documents folder */
2501 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2504 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2505 ".documents", NULL);
2507 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2508 g_free (docs_folder);
2510 g_free (conf_folder);
2511 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2512 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2513 GTK_WINDOW (dialog), GTK_WINDOW (window));
2515 /* Connect to response & show */
2516 g_signal_connect (dialog, "response",
2517 G_CALLBACK (on_attach_file_response), window);
2518 gtk_widget_show (dialog);
2523 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2525 GnomeVFSFileSize allowed_size)
2528 GnomeVFSHandle *handle = NULL;
2529 ModestMsgEditWindowPrivate *priv;
2530 GnomeVFSResult result;
2531 GnomeVFSFileSize size = 0;
2532 g_return_val_if_fail (window, 0);
2533 g_return_val_if_fail (uri, 0);
2535 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2537 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2538 if (result == GNOME_VFS_OK) {
2539 TnyMimePart *mime_part;
2541 const gchar *mime_type = NULL;
2543 gchar *escaped_filename;
2546 GnomeVFSFileInfo *info;
2547 GnomeVFSURI *vfs_uri;
2549 gnome_vfs_close (handle);
2550 vfs_uri = gnome_vfs_uri_new (uri);
2553 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2554 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2555 g_free (escaped_filename);
2556 gnome_vfs_uri_unref (vfs_uri);
2558 info = gnome_vfs_file_info_new ();
2560 if (gnome_vfs_get_file_info (uri,
2562 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2564 mime_type = gnome_vfs_file_info_get_mime_type (info);
2565 mime_part = tny_platform_factory_new_mime_part
2566 (modest_runtime_get_platform_factory ());
2568 /* try to get the attachment's size; this may fail for weird
2569 * file systems, like obex, upnp... */
2570 if (allowed_size != 0 &&
2571 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2573 if (size > allowed_size) {
2574 modest_platform_information_banner (NULL, NULL,
2575 _("mail_ib_error_attachment_size"));
2580 g_debug ("%s: could not get attachment size", __FUNCTION__);
2582 stream = create_stream_for_uri (uri);
2584 if (stream == NULL) {
2586 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2588 g_object_unref (mime_part);
2590 gnome_vfs_file_info_unref (info);
2594 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2595 g_object_unref (stream);
2597 content_id = g_strdup_printf ("%d", priv->next_cid);
2598 tny_mime_part_set_content_id (mime_part, content_id);
2599 g_free (content_id);
2602 basename = g_path_get_basename (filename);
2603 tny_mime_part_set_filename (mime_part, basename);
2606 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2607 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2609 info->size == 0, info->size);
2610 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2611 gtk_widget_show_all (priv->attachments_caption);
2612 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2614 g_object_unref (mime_part);
2615 gnome_vfs_file_info_unref (info);
2622 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2625 ModestMsgEditWindowPrivate *priv;
2628 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2629 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2631 if (att_list == NULL) {
2632 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2633 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2634 g_object_unref (att_list);
2638 g_object_ref (att_list);
2641 if (tny_list_get_length (att_list) == 0) {
2642 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2644 gboolean dialog_response;
2645 gchar *message = NULL;
2646 gchar *filename = NULL;
2648 if (tny_list_get_length (att_list) == 1) {
2650 iter = tny_list_create_iterator (att_list);
2651 part = (TnyMimePart *) tny_iterator_get_current (iter);
2652 g_object_unref (iter);
2653 if (TNY_IS_MSG (part)) {
2654 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2656 filename = tny_header_dup_subject (header);
2657 g_object_unref (header);
2659 if (filename == NULL) {
2660 filename = g_strdup (_("mail_va_no_subject"));
2663 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2665 g_object_unref (part);
2667 filename = g_strdup ("");
2669 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2670 "emev_nc_delete_attachments",
2671 tny_list_get_length (att_list)), filename);
2674 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2678 if (dialog_response != GTK_RESPONSE_OK) {
2679 g_object_unref (att_list);
2683 for (iter = tny_list_create_iterator (att_list);
2684 !tny_iterator_is_done (iter);
2685 tny_iterator_next (iter)) {
2686 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2687 const gchar *att_id;
2688 tny_list_remove (priv->attachments, (GObject *) mime_part);
2690 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2692 if (tny_list_get_length (priv->attachments) == 0)
2693 gtk_widget_hide (priv->attachments_caption);
2694 att_id = tny_mime_part_get_content_id (mime_part);
2696 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2698 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2699 g_object_unref (mime_part);
2701 g_object_unref (iter);
2704 g_object_unref (att_list);
2706 /* if the last attachment has been removed, focus the Subject: field */
2707 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2708 gtk_widget_grab_focus (priv->subject_field);
2712 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2715 ModestMsgEditWindowPrivate *priv;
2718 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2720 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &new_color);
2722 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2724 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2728 font_size_clicked (GtkToolButton *button,
2729 ModestMsgEditWindow *window)
2731 ModestMsgEditWindowPrivate *priv;
2732 GtkWidget *selector, *dialog;
2734 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2736 selector = hildon_touch_selector_new ();
2737 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2738 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2740 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2741 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2742 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2744 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2748 WPTextBufferFormat format;
2750 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2752 memset (&format, 0, sizeof (format));
2753 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2755 format.cs.font_size = TRUE;
2756 format.cs.text_position = TRUE;
2757 format.cs.font = TRUE;
2758 format.font_size = new_index;
2759 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2761 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2762 GINT_TO_POINTER (new_index)))
2763 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2765 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2766 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2767 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2768 size_text, "</span>", NULL);
2770 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2774 gtk_widget_destroy (dialog);
2776 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2781 font_face_clicked (GtkToolButton *button,
2782 ModestMsgEditWindow *window)
2784 ModestMsgEditWindowPrivate *priv;
2785 GtkWidget *selector, *dialog;
2786 GtkCellRenderer *renderer;
2788 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2790 selector = hildon_touch_selector_new ();
2791 renderer = gtk_cell_renderer_text_new ();
2792 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2793 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2794 renderer, "family", 0, "text", 0, NULL);
2795 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2797 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2798 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2799 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2801 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2802 gint new_font_index;
2806 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2807 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2808 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2812 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2814 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2815 GINT_TO_POINTER(new_font_index)))
2816 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2818 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2819 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2821 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2825 gtk_tree_path_free (path);
2828 gtk_widget_destroy (dialog);
2830 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2835 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2838 ModestMsgEditWindowPrivate *priv = NULL;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2841 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2842 if (!priv->update_caption_visibility)
2845 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2847 gtk_widget_show (priv->cc_caption);
2849 gtk_widget_hide (priv->cc_caption);
2851 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2855 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2858 ModestMsgEditWindowPrivate *priv = NULL;
2859 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2861 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2862 if (!priv->update_caption_visibility)
2865 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2867 gtk_widget_show (priv->bcc_caption);
2869 gtk_widget_hide (priv->bcc_caption);
2871 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2875 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2876 ModestRecptEditor *editor)
2878 ModestMsgEditWindowPrivate *priv;
2880 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2881 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2883 /* we check for low-mem; in that case, show a warning, and don't allow
2884 * for the addressbook
2886 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2889 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2891 if (editor == NULL) {
2892 GtkWidget *view_focus, *parent;
2893 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2895 /* This code should be kept in sync with ModestRecptEditor. The
2896 textview inside the recpt editor is the one that really gets the
2897 focus. As it's inside a scrolled window, and this one inside the
2898 hbox recpt editor inherits from, we'll need to go up in the
2899 hierarchy to know if the text view is part of the recpt editor
2900 or if it's a different text entry */
2901 parent = gtk_widget_get_parent (view_focus);
2902 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2903 editor = MODEST_RECPT_EDITOR (parent);
2906 editor = MODEST_RECPT_EDITOR (priv->to_field);
2909 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2913 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2915 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2917 modest_msg_edit_window_open_addressbook (window, NULL);
2921 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2922 gboolean show_toolbar)
2924 ModestWindowPrivate *parent_priv;
2925 ModestMsgEditWindowPrivate *priv;
2927 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2928 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2929 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2931 /* We can not just use the code of
2932 modest_msg_edit_window_setup_toolbar because it has a
2933 mixture of both initialization and creation code. */
2935 gint current_format;
2936 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2937 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2938 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2939 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2941 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2944 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2949 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2950 TnyHeaderFlags priority_flags)
2952 ModestMsgEditWindowPrivate *priv;
2953 ModestWindowPrivate *parent_priv;
2955 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2958 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2960 if (priv->priority_flags != priority_flags) {
2961 GtkAction *priority_action = NULL;
2963 priv->priority_flags = priority_flags;
2965 switch (priority_flags) {
2966 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2967 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2968 MODEST_HEADER_ICON_HIGH,
2969 HILDON_ICON_SIZE_SMALL);
2970 gtk_widget_show (priv->priority_icon);
2971 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2972 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2974 case TNY_HEADER_FLAG_LOW_PRIORITY:
2975 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2976 MODEST_HEADER_ICON_LOW,
2977 HILDON_ICON_SIZE_SMALL);
2978 gtk_widget_show (priv->priority_icon);
2979 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2980 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2983 gtk_widget_hide (priv->priority_icon);
2984 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2985 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2988 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2989 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2991 gtk_widget_queue_resize (priv->subject_box);
2995 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2998 ModestMsgEditWindowPrivate *priv;
2999 ModestWindowPrivate *parent_priv;
3000 gint current_format;
3002 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3004 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3007 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3008 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3010 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3012 if (current_format != file_format) {
3013 switch (file_format) {
3014 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3015 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3016 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3017 if (parent_priv->toolbar)
3018 gtk_widget_show (parent_priv->toolbar);
3020 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3024 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3025 response = gtk_dialog_run (GTK_DIALOG (dialog));
3026 gtk_widget_destroy (dialog);
3027 if (response == GTK_RESPONSE_OK) {
3028 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3029 if (parent_priv->toolbar)
3030 gtk_widget_hide (parent_priv->toolbar);
3032 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3033 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3038 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3039 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3040 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3045 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3048 ModestMsgEditWindowPrivate *priv;
3049 WPTextBufferFormat oldfmt, fmt;
3050 gint old_position = 0;
3054 GdkColor *color = NULL;
3055 gboolean bold, bold_set, italic, italic_set;
3056 gboolean underline, underline_set;
3057 gboolean strikethrough, strikethrough_set;
3058 gboolean position_set;
3059 gboolean font_size_set, font_set, color_set;
3062 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3063 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3065 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3066 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3067 GTK_WINDOW(dialog), GTK_WINDOW (window));
3069 /* First we get the currently selected font information */
3070 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3072 switch (oldfmt.text_position) {
3073 case TEXT_POSITION_NORMAL:
3076 case TEXT_POSITION_SUPERSCRIPT:
3084 g_object_set (G_OBJECT (dialog),
3085 "bold", oldfmt.bold != FALSE,
3086 "bold-set", !oldfmt.cs.bold,
3087 "underline", oldfmt.underline != FALSE,
3088 "underline-set", !oldfmt.cs.underline,
3089 "italic", oldfmt.italic != FALSE,
3090 "italic-set", !oldfmt.cs.italic,
3091 "strikethrough", oldfmt.strikethrough != FALSE,
3092 "strikethrough-set", !oldfmt.cs.strikethrough,
3093 "color", &oldfmt.color,
3094 "color-set", !oldfmt.cs.color,
3095 "size", wp_font_size[oldfmt.font_size],
3096 "size-set", !oldfmt.cs.font_size,
3097 "position", old_position,
3098 "position-set", !oldfmt.cs.text_position,
3099 "family", wp_get_font_name (oldfmt.font),
3100 "family-set", !oldfmt.cs.font,
3103 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3104 GTK_WINDOW (dialog), GTK_WINDOW (window));
3105 gtk_widget_show_all (dialog);
3106 priv->font_dialog = dialog;
3107 response = gtk_dialog_run (GTK_DIALOG (dialog));
3108 priv->font_dialog = NULL;
3109 if (response == GTK_RESPONSE_OK) {
3111 g_object_get( dialog,
3113 "bold-set", &bold_set,
3114 "underline", &underline,
3115 "underline-set", &underline_set,
3117 "italic-set", &italic_set,
3118 "strikethrough", &strikethrough,
3119 "strikethrough-set", &strikethrough_set,
3121 "color-set", &color_set,
3123 "size-set", &font_size_set,
3124 "family", &font_name,
3125 "family-set", &font_set,
3126 "position", &position,
3127 "position-set", &position_set,
3132 if (response == GTK_RESPONSE_OK) {
3133 memset(&fmt, 0, sizeof(fmt));
3139 fmt.italic = italic;
3140 fmt.cs.italic = TRUE;
3142 if (underline_set) {
3143 fmt.underline = underline;
3144 fmt.cs.underline = TRUE;
3146 if (strikethrough_set) {
3147 fmt.strikethrough = strikethrough;
3148 fmt.cs.strikethrough = TRUE;
3153 ? TEXT_POSITION_NORMAL
3154 : ( ( position == 1 )
3155 ? TEXT_POSITION_SUPERSCRIPT
3156 : TEXT_POSITION_SUBSCRIPT );
3157 fmt.cs.text_position = TRUE;
3158 fmt.font_size = oldfmt.font_size;
3162 fmt.cs.color = TRUE;
3165 fmt.font = wp_get_font_index(font_name,
3170 if (font_size_set) {
3171 fmt.cs.font_size = TRUE;
3172 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3174 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3175 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3177 gtk_widget_destroy (dialog);
3179 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3183 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3185 ModestMsgEditWindowPrivate *priv;
3186 ModestWindowPrivate *parent_priv;
3187 gboolean was_rich_text, is_rich_text;
3189 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3190 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3191 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3193 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3195 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3197 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3199 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3201 gtk_widget_show (parent_priv->toolbar);
3203 gtk_widget_hide (parent_priv->toolbar);
3206 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3207 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3211 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3213 ModestMsgEditWindowPrivate *priv;
3215 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3216 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3218 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3220 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3221 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3226 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3228 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3230 priv->can_undo = can_undo;
3234 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3236 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3238 priv->can_redo = can_redo;
3242 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3244 ModestMsgEditWindowPrivate *priv;
3245 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3246 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3248 return priv->can_undo;
3252 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3254 ModestMsgEditWindowPrivate *priv;
3255 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 return priv->can_redo;
3263 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3266 GtkTextIter match_start, match_end;
3268 if (image_id == NULL)
3271 gtk_text_buffer_get_start_iter (buffer, &iter);
3273 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3274 GSList *tags = gtk_text_iter_get_tags (&match_start);
3276 for (node = tags; node != NULL; node = g_slist_next (node)) {
3277 GtkTextTag *tag = (GtkTextTag *) node->data;
3278 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3279 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3280 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3282 offset = gtk_text_iter_get_offset (&match_start);
3283 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3284 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3288 gtk_text_iter_forward_char (&iter);
3293 message_is_empty (ModestMsgEditWindow *window)
3295 ModestMsgEditWindowPrivate *priv = NULL;
3297 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3300 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3301 * so we can ignore markup.
3303 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3306 count = gtk_text_buffer_get_char_count (buf);
3312 msg_body_focus (GtkWidget *focus,
3313 GdkEventFocus *event,
3317 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3318 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3319 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3324 recpt_field_changed (GtkTextBuffer *buffer,
3325 ModestMsgEditWindow *editor)
3327 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3328 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3332 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3334 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3335 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3339 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3342 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3343 GtkTextBuffer *buffer;
3345 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3346 gtk_text_buffer_set_modified (buffer, modified);
3347 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3348 gtk_text_buffer_set_modified (buffer, modified);
3349 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3350 gtk_text_buffer_set_modified (buffer, modified);
3351 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3355 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3357 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3358 const char *account_name;
3359 GtkTextBuffer *buffer;
3361 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3362 if (gtk_text_buffer_get_modified (buffer))
3364 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3365 if (gtk_text_buffer_get_modified (buffer))
3367 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3368 if (gtk_text_buffer_get_modified (buffer))
3370 if (gtk_text_buffer_get_modified (priv->text_buffer))
3373 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3374 if (priv->original_mailbox) {
3375 if (!account_name || strcmp (account_name, priv->original_mailbox))
3377 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3388 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3390 ModestMsgEditWindowPrivate *priv = NULL;
3391 GSList *address_list = NULL;
3393 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3396 /* check if there's no recipient added */
3397 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3398 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3399 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3400 /* no recipient contents, then select contacts */
3401 modest_msg_edit_window_open_addressbook (window, NULL);
3406 g_object_ref (window);
3407 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3408 (add_to_addressbook) ? &address_list : NULL)) {
3409 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3410 g_object_unref (window);
3413 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3414 (add_to_addressbook) ? &address_list : NULL)) {
3415 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3416 g_object_unref (window);
3419 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3420 (add_to_addressbook) ? &address_list : NULL)) {
3421 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3422 g_object_unref (window);
3426 /* Add contacts to address book */
3427 if (add_to_addressbook && address_list)
3428 modest_address_book_add_address_list (address_list);
3430 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3431 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3432 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3433 g_object_unref (window);
3440 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3442 GSList *recipients = NULL;
3443 ModestMsgEditWindowPrivate *priv;
3444 gchar *joined, *after_remove, *to, *cc, *bcc;
3446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3448 /* First of all check names */
3449 if (!modest_msg_edit_window_check_names (self, FALSE))
3452 if (!modest_msg_edit_window_has_pending_addresses (self))
3455 /* Don't add the from obviously */
3456 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3457 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3458 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3460 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3465 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3468 recipients = modest_text_utils_split_addresses_list (after_remove);
3469 g_free (after_remove);
3472 /* Offer the user to add recipients to the address book */
3473 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3474 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3479 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3480 ModestMsgEditWindow *window)
3482 modest_msg_edit_window_offer_attach_file (window);
3486 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3488 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3490 return priv->clipboard_text;
3494 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3496 ModestMsgEditWindow *window)
3498 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3499 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3502 /* It could happen that the window was already closed */
3503 if (!GTK_WIDGET_VISIBLE (window))
3506 g_object_ref (window);
3507 text = gtk_clipboard_wait_for_text (selection_clipboard);
3509 if (priv->clipboard_text != NULL) {
3510 g_free (priv->clipboard_text);
3512 priv->clipboard_text = text;
3514 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3516 g_object_unref (window);
3519 static gboolean clipboard_owner_change_idle (gpointer userdata)
3521 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3522 ModestMsgEditWindowPrivate *priv;
3524 gdk_threads_enter ();
3525 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3528 priv->clipboard_owner_idle = 0;
3529 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3530 gdk_threads_leave ();
3536 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3538 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3539 if (priv->clipboard_owner_idle == 0) {
3540 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3541 clipboard_owner_change_idle,
3542 g_object_ref (window),
3548 subject_field_move_cursor (GtkEntry *entry,
3549 GtkMovementStep step,
3554 /* It could happen that the window was already closed */
3555 if (!GTK_WIDGET_VISIBLE (window))
3558 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3562 update_window_title (ModestMsgEditWindow *window)
3564 ModestMsgEditWindowPrivate *priv = NULL;
3565 const gchar *subject;
3567 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3568 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3569 if (subject == NULL || subject[0] == '\0')
3570 subject = _("mail_va_new_email");
3572 gtk_window_set_title (GTK_WINDOW (window), subject);
3578 body_insert_text (GtkTextBuffer *buffer,
3579 GtkTextIter *location,
3582 ModestMsgEditWindow *window)
3584 GtkTextIter end_iter;
3591 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3593 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3595 offset = gtk_text_iter_get_offset (&end_iter);
3596 line = gtk_text_iter_get_line (&end_iter);
3600 while (text_offset < text + len) {
3601 if (*text_offset == '\n')
3603 if (text_lines + line >= MAX_BODY_LINES) {
3604 len = text_offset - text;
3610 utf8_len = g_utf8_strlen (text, len);
3612 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3613 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3614 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3619 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3621 /* Prevent endless recursion */
3622 result = g_strndup (text, utf8_end - text);
3623 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3624 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3625 (gpointer) result, (gpointer) (utf8_end - text),
3627 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3631 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3632 if (priv->max_chars_banner == NULL) {
3633 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3634 _CS("ckdg_ib_maximum_characters_reached"));
3635 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3641 subject_field_changed (GtkEditable *editable,
3642 ModestMsgEditWindow *window)
3644 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3645 update_window_title (window);
3646 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3647 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3648 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3651 subject_field_insert_text (GtkEditable *editable,
3653 gint new_text_length,
3655 ModestMsgEditWindow *window)
3657 GString *result = g_string_new ("");
3659 gint result_len = 0;
3660 const gchar *entry_text = NULL;
3663 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3664 old_length = g_utf8_strlen (entry_text, -1);
3666 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3667 gunichar c = g_utf8_get_char_validated (current, 8);
3668 /* Invalid unichar, stop */
3674 result = g_string_append_unichar (result, c);
3678 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3679 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3682 /* Prevent endless recursion */
3683 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3684 g_signal_emit_by_name (editable, "insert-text",
3685 (gpointer) result->str, (gpointer) result->len,
3686 (gpointer) position, (gpointer) window);
3687 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3691 if (result_len + old_length > 1000) {
3692 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3693 _CS("ckdg_ib_maximum_characters_reached"));
3695 g_string_free (result, TRUE);
3699 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3702 ModestMsgEditWindowPrivate *priv = NULL;
3704 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3705 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3707 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3710 gtk_widget_show_all (priv->find_toolbar);
3711 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3713 gtk_widget_hide_all (priv->find_toolbar);
3714 gtk_widget_grab_focus (priv->msg_body);
3719 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3721 GtkTextIter *match_start,
3722 GtkTextIter *match_end)
3724 GtkTextIter end_iter;
3725 gchar *str_casefold;
3728 gchar *range_casefold;
3731 gboolean result = FALSE;
3738 gtk_text_iter_forward_to_end (&end_iter);
3740 str_casefold = g_utf8_casefold (str, -1);
3741 str_chars_n = strlen (str);
3743 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3744 range_casefold = g_utf8_casefold (range_text, -1);
3745 range_chars_n = strlen (range_casefold);
3747 if (range_chars_n < str_chars_n) {
3748 g_free (str_casefold);
3749 g_free (range_text);
3750 g_free (range_casefold);
3754 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3755 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3756 if (!g_utf8_collate (range_subtext, str_casefold)) {
3757 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3759 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3760 match_start, match_end, NULL)) {
3761 g_debug ("Matched string with collate, but not matched in model");
3763 g_free (found_text);
3765 g_free (range_subtext);
3769 g_free (str_casefold);
3770 g_free (range_text);
3771 g_free (range_casefold);
3778 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3779 ModestMsgEditWindow *window)
3781 gchar *current_search = NULL;
3782 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3784 GtkTextIter selection_start, selection_end;
3785 GtkTextIter match_start, match_end;
3786 gboolean continue_search = FALSE;
3788 if (message_is_empty (window)) {
3789 g_free (priv->last_search);
3790 priv->last_search = NULL;
3791 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3795 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3796 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3797 g_free (current_search);
3798 g_free (priv->last_search);
3799 priv->last_search = NULL;
3800 /* Information banner about empty search */
3801 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3805 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3806 continue_search = TRUE;
3808 g_free (priv->last_search);
3809 priv->last_search = g_strdup (current_search);
3812 if (continue_search) {
3813 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3814 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3815 &match_start, &match_end);
3817 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3819 GtkTextIter buffer_start;
3820 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3821 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3822 &match_start, &match_end);
3824 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3827 /* Mark as selected the string found in search */
3829 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3830 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3831 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3833 g_free (priv->last_search);
3834 priv->last_search = NULL;
3836 g_free (current_search);
3840 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3842 ModestMsgEditWindowPrivate *priv;
3844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3849 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3852 ModestMsgEditWindowPrivate *priv;
3854 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3859 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3860 ModestMsgEditWindow *window)
3862 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3866 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3869 ModestMsgEditWindowPrivate *priv;
3870 TnyHeader *header = NULL;
3872 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3873 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3875 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3877 if (priv->draft_msg != NULL) {
3878 g_object_unref (priv->draft_msg);
3881 if (draft != NULL) {
3882 g_object_ref (draft);
3883 header = tny_msg_get_header (draft);
3884 if (priv->msg_uid) {
3885 g_free (priv->msg_uid);
3886 priv->msg_uid = NULL;
3888 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3891 priv->draft_msg = draft;
3895 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3896 GtkTextIter *start, GtkTextIter *end,
3899 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3900 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3903 if (tag == NULL) return;
3904 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3905 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3906 replace_with_images (window, priv->images);
3911 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3914 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3916 g_return_if_fail (TNY_IS_MIME_PART (part));
3917 tny_list_prepend (priv->attachments, (GObject *) part);
3918 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3919 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3920 gtk_widget_show_all (priv->attachments_caption);
3921 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3925 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3927 ModestMsgEditWindowPrivate *priv;
3929 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3932 return priv->msg_uid;
3936 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3937 ModestMsgEditWindowWidgetType widget_type)
3939 ModestMsgEditWindowPrivate *priv;
3941 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3942 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3944 switch (widget_type) {
3945 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3946 return priv->msg_body;
3948 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3949 return priv->to_field;
3951 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3952 return priv->cc_field;
3954 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3955 return priv->bcc_field;
3957 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3958 return priv->subject_field;
3960 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3961 return priv->attachments_view;
3969 remove_tags (WPTextBuffer *buffer)
3971 GtkTextIter start, end;
3973 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3974 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3976 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3980 on_account_removed (TnyAccountStore *account_store,
3981 TnyAccount *account,
3984 /* Do nothing if it's a store account, because we use the
3985 transport to send the messages */
3986 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3987 const gchar *parent_acc = NULL;
3988 const gchar *our_acc = NULL;
3990 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3991 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3992 /* Close this window if I'm showing a message of the removed account */
3993 if (strcmp (parent_acc, our_acc) == 0)
3994 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3999 update_signature (ModestMsgEditWindow *self,
4000 const gchar *old_account,
4001 const gchar *new_account)
4003 ModestMsgEditWindowPrivate *priv;
4004 gboolean has_old_signature, has_new_signature;
4006 ModestAccountMgr *mgr;
4009 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4011 gtk_text_buffer_begin_user_action (priv->text_buffer);
4013 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4014 mgr = modest_runtime_get_account_mgr ();
4018 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4019 if (has_old_signature) {
4020 GtkTextIter match_start, match_end;
4022 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4023 seems that the search has some problems
4024 with the blank space at the end */
4025 if (gtk_text_iter_forward_search (&iter, "--",
4026 GTK_TEXT_SEARCH_TEXT_ONLY,
4027 &match_start, NULL, NULL)) {
4028 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4029 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4031 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4032 &match_start, &match_end, NULL)) {
4036 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4041 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4042 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4043 if (has_new_signature) {
4046 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4047 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4049 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4051 WPTextBufferFormat *fmt;
4052 GdkColor style_color;
4053 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4054 gdk_color_parse ("grey", &style_color);
4056 fmt = g_new0 (WPTextBufferFormat, 1);
4057 fmt->color = style_color;
4058 fmt->cs.color = 0x1;
4059 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4063 g_free (full_signature);
4065 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4069 gtk_text_buffer_end_user_action (priv->text_buffer);
4072 static void update_branding (ModestMsgEditWindow *self,
4073 const gchar *new_account)
4075 ModestMsgEditWindowPrivate *priv;
4076 ModestAccountMgr *mgr;
4077 const GdkPixbuf *new_icon = NULL;
4078 gchar *new_label = NULL;
4079 gboolean show = FALSE;
4081 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4083 mgr = modest_runtime_get_account_mgr ();
4085 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4087 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4088 gtk_widget_show (priv->brand_icon);
4091 gtk_widget_hide (priv->brand_icon);
4094 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4095 gtk_widget_show (priv->brand_label);
4099 gtk_widget_hide (priv->brand_label);
4103 gtk_widget_show (priv->brand_container);
4105 gtk_widget_hide (priv->brand_container);
4109 from_field_changed (HildonPickerButton *button,
4110 ModestMsgEditWindow *self)
4112 ModestMsgEditWindowPrivate *priv;
4113 gchar *old_account, *new_account;
4115 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4117 old_account = priv->last_from_account;
4118 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4121 g_warning ("%s, could not get the new account", __FUNCTION__);
4125 /* If the From is the same do nothing */
4126 if (old_account && new_account && !strcmp (old_account, new_account))
4129 priv->last_from_account = new_account;
4131 update_signature (self, old_account, new_account);
4132 update_branding (self, new_account);
4136 typedef struct _MessageSettingsHelper {
4137 ModestMsgEditWindow *window;
4138 GSList *priority_group;
4139 GSList *format_group;
4140 GtkToggleButton *current_priority;
4141 GtkToggleButton *current_format;
4142 } MessageSettingsHelper;
4145 on_priority_toggle (GtkToggleButton *button,
4146 MessageSettingsHelper *helper)
4149 ModestMsgEditWindowPrivate *priv;
4151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4152 if (gtk_toggle_button_get_active (button)) {
4154 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4155 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4156 if ((node_button != button) &&
4157 gtk_toggle_button_get_active (node_button)) {
4158 gtk_toggle_button_set_active (node_button, FALSE);
4161 helper->current_priority = button;
4163 gboolean found = FALSE;
4164 /* If no one is active, activate it again */
4165 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4166 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4167 if (gtk_toggle_button_get_active (node_button)) {
4173 gtk_toggle_button_set_active (button, TRUE);
4179 on_format_toggle (GtkToggleButton *button,
4180 MessageSettingsHelper *helper)
4183 ModestMsgEditWindowPrivate *priv;
4185 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4186 if (gtk_toggle_button_get_active (button)) {
4188 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4189 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4190 if ((node_button != button) &&
4191 gtk_toggle_button_get_active (node_button)) {
4192 gtk_toggle_button_set_active (node_button, FALSE);
4195 helper->current_format = button;
4197 gboolean found = FALSE;
4198 /* If no one is active, activate it again */
4199 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4200 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4201 if (gtk_toggle_button_get_active (node_button)) {
4207 gtk_toggle_button_set_active (button, TRUE);
4214 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4219 GtkWidget *priority_hbox;
4220 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4221 GtkWidget *captioned;
4222 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4223 GtkWidget *format_hbox;
4224 GtkWidget *html_toggle, *text_toggle;
4225 ModestMsgEditWindowPrivate *priv;
4226 MessageSettingsHelper helper = {0,};
4228 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4230 helper.window = window;
4231 helper.priority_group = NULL;
4232 helper.format_group = NULL;
4234 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4235 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4237 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4238 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4239 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4240 vbox = gtk_vbox_new (FALSE, 0);
4241 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4242 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4243 gtk_container_add (GTK_CONTAINER (align), vbox);
4244 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4245 gtk_widget_show (align);
4246 gtk_widget_show (vbox);
4248 /* Priority toggles */
4249 priority_hbox = gtk_hbox_new (TRUE, 0);
4250 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4251 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4252 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4253 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4254 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4255 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4256 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4257 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4258 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4259 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4260 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4261 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4262 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4263 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4264 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4265 gtk_widget_show_all (priority_hbox);
4266 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4267 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4268 gtk_widget_show (captioned);
4269 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4271 /* format toggles */
4272 format_hbox = gtk_hbox_new (TRUE, 0);
4273 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4274 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4275 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4276 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4277 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4278 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4279 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4280 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4281 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4282 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4283 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4284 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4285 gtk_widget_show_all (format_hbox);
4286 gtk_widget_show (format_hbox);
4287 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4290 g_object_unref (title_sizegroup);
4291 g_object_unref (value_sizegroup);
4293 /* Set current values */
4294 switch (priv->priority_flags) {
4295 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4296 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4297 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4299 case TNY_HEADER_FLAG_LOW_PRIORITY:
4300 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4301 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4304 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4305 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4309 switch (modest_msg_edit_window_get_format (window)) {
4310 case MODEST_MSG_EDIT_FORMAT_TEXT:
4311 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4312 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4314 case MODEST_MSG_EDIT_FORMAT_HTML:
4316 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4317 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4321 /* Signal connects */
4322 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4323 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4324 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4325 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4326 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4328 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4329 GTK_WINDOW (dialog), GTK_WINDOW (window));
4331 /* Save settings if the user clicked on done */
4332 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4333 TnyHeaderFlags flags;
4334 ModestMsgEditFormat old_format, new_format;
4336 /* Set priority flags */
4337 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4338 if (priv->priority_flags != flags)
4339 modest_msg_edit_window_set_priority_flags (window, flags);
4341 /* Set edit format */
4342 old_format = modest_msg_edit_window_get_format (window);
4343 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4344 if (old_format != new_format) {
4345 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4346 modest_msg_edit_window_set_file_format (window, file_format);
4350 gtk_widget_destroy (dialog);
4351 g_slist_free (helper.priority_group);
4355 on_message_settings (GtkAction *action,
4356 ModestMsgEditWindow *window)
4358 modest_msg_edit_window_show_msg_settings_dialog (window);
4362 on_cc_button_toggled (HildonCheckButton *button,
4363 ModestMsgEditWindow *window)
4365 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4367 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4368 hildon_check_button_get_active (button));
4372 on_bcc_button_toggled (HildonCheckButton *button,
4373 ModestMsgEditWindow *window)
4375 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4377 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4378 hildon_check_button_get_active (button));
4382 setup_menu (ModestMsgEditWindow *self)
4384 ModestMsgEditWindowPrivate *priv = NULL;
4386 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4388 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4390 /* Settings menu buttons */
4391 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4392 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4394 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4395 APP_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4396 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4397 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4398 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4399 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4401 priv->cc_button = hildon_check_button_new (0);
4402 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4403 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4405 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4407 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4408 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4409 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4410 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4412 priv->bcc_button = hildon_check_button_new (0);
4413 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4414 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4416 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4418 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4419 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4420 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4421 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4423 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4424 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4425 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4426 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4427 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4429 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4430 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4431 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4432 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4433 APP_MENU_CALLBACK (on_message_settings),
4435 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4436 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4441 emit_open_addressbook (GtkButton *button,
4442 ModestRecptEditor *editor)
4444 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4448 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4449 const gchar *label, GtkWidget *control)
4451 GtkWidget *abook_button;
4454 GtkWidget *label_widget;
4456 box = gtk_hbox_new (FALSE, 0);
4458 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4459 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4461 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4462 label_widget = gtk_label_new (label);
4463 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4464 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4466 gtk_container_add (GTK_CONTAINER (align), abook_button);
4467 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4468 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4469 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4470 if (title_size_group)
4471 gtk_size_group_add_widget (title_size_group, label_widget);
4472 if (value_size_group)
4473 gtk_size_group_add_widget (value_size_group, control);
4475 g_signal_connect (G_OBJECT (abook_button), "clicked",
4476 G_CALLBACK (emit_open_addressbook), control);
4482 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4484 ModestMsgEditWindowPrivate *priv = NULL;
4486 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4488 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4489 priv->max_chars_banner = NULL;
4493 has_pending_addresses (ModestRecptEditor *recpt_editor)
4495 const gchar *recipients = NULL;
4496 GSList *start_indexes = NULL, *end_indexes = NULL;
4497 GSList *current_start, *current_end;
4498 GtkTextBuffer *buffer;
4499 gint offset_delta = 0;
4501 gboolean has_recipients_to_add = FALSE;
4503 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4504 last_length = g_utf8_strlen (recipients, -1);
4505 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4510 current_start = start_indexes;
4511 current_end = end_indexes;
4512 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4514 while (current_start && !has_recipients_to_add) {
4516 gchar *start_ptr, *end_ptr;
4517 gint start_pos, end_pos;
4519 start_pos = (*((gint*) current_start->data)) + offset_delta;
4520 end_pos = (*((gint*) current_end->data)) + offset_delta;
4522 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4523 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4525 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4527 if (modest_text_utils_validate_recipient (address, NULL)) {
4528 if (!modest_address_book_has_address (address)) {
4529 has_recipients_to_add = TRUE;
4532 current_start = g_slist_next (current_start);
4533 current_end = g_slist_next (current_end);
4535 return has_recipients_to_add;
4539 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4541 ModestMsgEditWindowPrivate *priv = NULL;
4543 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4545 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4547 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4548 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4549 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))