1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #include <libgnomevfs/gnome-vfs-mime.h>
75 #include <modest-utils.h>
76 #include "modest-maemo-utils.h"
77 #include <modest-ui-constants.h>
78 #include "modest-color-button.h"
80 #ifdef MODEST_USE_CALENDAR_WIDGETS
81 #include <calendar-ui-widgets.h>
84 #define DEFAULT_FONT_SIZE 3
85 #define DEFAULT_FONT 2
86 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
87 #define DEFAULT_MAIN_VBOX_SPACING 0
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
91 #define ATTACHMENT_BUTTON_WIDTH 118
92 #define MAX_FROM_VALUE 36
93 #define MAX_BODY_LENGTH 128*1024
94 #define MAX_BODY_LINES 2048
96 static gboolean is_wp_text_buffer_started = FALSE;
98 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
99 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
100 static void modest_msg_edit_window_finalize (GObject *obj);
102 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
103 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
104 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
107 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
108 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
109 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
110 GtkTextIter *start, GtkTextIter *end,
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void body_insert_text (GtkTextBuffer *buffer,
114 GtkTextIter *location,
117 ModestMsgEditWindow *window);
118 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
119 static void subject_field_insert_text (GtkEditable *editable,
121 gint new_text_length,
123 ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
128 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
129 ModestRecptEditor *editor);
130 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
131 ModestMsgEditWindow *window);
133 /* ModestWindow methods implementation */
134 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
135 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
136 gboolean show_toolbar);
137 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
139 ModestMsgEditWindow *window);
140 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
141 static void subject_field_move_cursor (GtkEntry *entry,
142 GtkMovementStep step,
146 static void update_window_title (ModestMsgEditWindow *window);
149 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
150 ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
155 GtkTextIter *match_start,
156 GtkTextIter *match_end);
158 static void remove_tags (WPTextBuffer *buffer);
160 static void on_account_removed (TnyAccountStore *account_store,
164 static void init_window (ModestMsgEditWindow *obj);
166 gboolean scroll_drag_timeout (gpointer userdata);
167 static void correct_scroll (ModestMsgEditWindow *w);
168 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
169 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void text_buffer_mark_set (GtkTextBuffer *buffer,
174 ModestMsgEditWindow *userdata);
175 static void on_show_toolbar_button_toggled (HildonCheckButton *button,
176 ModestMsgEditWindow *window);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static void update_branding (ModestMsgEditWindow *self,
191 const gchar *new_account);
192 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
193 const gchar *label, GtkWidget *control);
194 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
195 static void DEBUG_BUFFER (WPTextBuffer *buffer)
199 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
201 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
202 while (!gtk_text_iter_is_end (&iter)) {
203 GString *output = g_string_new ("");
204 GSList *toggled_tags;
207 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
208 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
209 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
210 GtkTextTag *tag = (GtkTextTag *) node->data;
212 g_object_get (G_OBJECT (tag), "name", &name, NULL);
213 output = g_string_append (output, name);
214 g_string_append (output, " ");
216 output = g_string_append (output, "] OPENED [ ");
217 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
218 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
219 GtkTextTag *tag = (GtkTextTag *) node->data;
221 g_object_get (G_OBJECT (tag), "name", &name, NULL);
222 output = g_string_append (output, name);
223 g_string_append (output, " ");
225 output = g_string_append (output, "]\n");
226 g_debug ("%s", output->str);
227 g_string_free (output, TRUE);
228 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
230 g_debug ("END BUFFER");
234 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
235 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
239 /* static gboolean */
240 /* on_key_pressed (GtkWidget *self, */
241 /* GdkEventKey *event, */
242 /* gpointer user_data); */
244 /* list my signals */
251 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
252 struct _ModestMsgEditWindowPrivate {
254 GtkWidget *header_box;
256 ModestPairList *from_field_protos;
257 GtkWidget *from_field;
258 gchar *last_from_account;
259 gchar *original_account_name;
264 gchar *original_mailbox;
268 GtkWidget *bcc_field;
269 GtkWidget *subject_field;
270 GtkWidget *attachments_view;
271 GtkWidget *priority_icon;
272 GtkWidget *subject_box;
273 GtkWidget *send_button;
275 GtkWidget *cc_caption;
276 GtkWidget *bcc_caption;
277 gboolean update_caption_visibility;
278 GtkWidget *attachments_caption;
280 GtkTextBuffer *text_buffer;
282 GtkWidget *font_size_toolitem;
283 GtkWidget *font_face_toolitem;
284 GtkWidget *font_color_button;
285 GtkWidget *font_color_toolitem;
286 GSList *font_items_group;
287 GtkTreeModel *faces_model;
288 gint current_face_index;
289 GtkWidget *font_tool_button_label;
290 GtkTreeModel *sizes_model;
291 gint current_size_index;
292 GtkWidget *size_tool_button_label;
294 GtkWidget *find_toolbar;
297 GtkWidget *font_dialog;
300 guint correct_scroll_idle;
301 guint scroll_drag_timeout_id;
305 TnyList *attachments;
310 TnyHeaderFlags priority_flags;
312 gboolean can_undo, can_redo;
313 gulong clipboard_change_handler_id;
314 gulong default_clipboard_change_handler_id;
315 gulong account_removed_handler_id;
316 guint clipboard_owner_idle;
317 gchar *clipboard_text;
326 GtkWidget *cc_button;
327 GtkWidget *bcc_button;
328 GtkWidget *show_toolbar_button;
330 GtkWidget *max_chars_banner;
332 GtkWidget *brand_icon;
333 GtkWidget *brand_label;
334 GtkWidget *brand_container;
336 TnyList *custom_header_pairs;
339 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
340 MODEST_TYPE_MSG_EDIT_WINDOW, \
341 ModestMsgEditWindowPrivate))
343 static GtkWindowClass *parent_class = NULL;
345 /* uncomment the following if you have defined any signals */
346 /* static guint signals[LAST_SIGNAL] = {0}; */
349 modest_msg_edit_window_get_type (void)
351 static GType my_type = 0;
353 static const GTypeInfo my_info = {
354 sizeof(ModestMsgEditWindowClass),
355 NULL, /* base init */
356 NULL, /* base finalize */
357 (GClassInitFunc) modest_msg_edit_window_class_init,
358 NULL, /* class finalize */
359 NULL, /* class data */
360 sizeof(ModestMsgEditWindow),
362 (GInstanceInitFunc) modest_msg_edit_window_init,
365 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
366 "ModestMsgEditWindow",
374 save_state (ModestWindow *self)
376 modest_widget_memory_save (modest_runtime_get_conf(),
377 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
382 restore_settings (ModestMsgEditWindow *self)
384 ModestConf *conf = NULL;
386 conf = modest_runtime_get_conf ();
388 /* Dim at start clipboard actions */
389 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
394 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
396 GObjectClass *gobject_class;
397 ModestWindowClass *modest_window_class;
398 gobject_class = (GObjectClass*) klass;
399 modest_window_class = (ModestWindowClass*) klass;
401 parent_class = g_type_class_peek_parent (klass);
402 gobject_class->finalize = modest_msg_edit_window_finalize;
404 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
405 modest_window_class->save_state_func = save_state;
406 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
408 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
412 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
414 ModestMsgEditWindowPrivate *priv;
415 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
417 priv->msg_body = NULL;
418 priv->from_field = NULL;
419 priv->to_field = NULL;
420 priv->cc_field = NULL;
421 priv->bcc_field = NULL;
422 priv->subject_field = NULL;
423 priv->attachments = TNY_LIST (tny_simple_list_new ());
424 priv->images = TNY_LIST (tny_simple_list_new ());
425 priv->images_size = 0;
426 priv->images_count = 0;
429 priv->cc_caption = NULL;
430 priv->bcc_caption = NULL;
431 priv->update_caption_visibility = FALSE;
433 priv->priority_flags = 0;
435 priv->find_toolbar = NULL;
436 priv->last_search = NULL;
438 priv->draft_msg = NULL;
439 priv->outbox_msg = NULL;
440 priv->msg_uid = NULL;
442 priv->can_undo = FALSE;
443 priv->can_redo = FALSE;
444 priv->clipboard_change_handler_id = 0;
445 priv->default_clipboard_change_handler_id = 0;
446 priv->account_removed_handler_id = 0;
447 priv->clipboard_owner_idle = 0;
448 priv->clipboard_text = NULL;
451 priv->scroll_drag_timeout_id = 0;
452 priv->correct_scroll_idle = 0;
453 priv->last_upper = 0.0;
455 priv->font_dialog = NULL;
456 priv->app_menu = NULL;
458 priv->references = NULL;
459 priv->in_reply_to = NULL;
460 priv->max_chars_banner = NULL;
461 priv->custom_header_pairs = TNY_LIST (tny_simple_list_new ());
463 if (!is_wp_text_buffer_started) {
464 is_wp_text_buffer_started = TRUE;
465 wp_text_buffer_library_init ();
470 hildon_program_add_window (hildon_program_get_instance(),
475 multimailbox_get_default_mailbox (const gchar *account_name)
477 gchar *transport_account;
478 gchar *result = NULL;
480 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
482 TNY_ACCOUNT_TYPE_TRANSPORT);
483 if (transport_account) {
485 ModestProtocolRegistry *registry;
487 registry = modest_runtime_get_protocol_registry ();
489 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
490 MODEST_ACCOUNT_PROTO, TRUE);
492 ModestProtocol *protocol =
493 modest_protocol_registry_get_protocol_by_name (registry,
494 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
496 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
497 ModestPairList *pair_list;
499 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
502 ModestPair *pair = (ModestPair *) pair_list->data;
503 result = g_strdup ((const gchar *) pair->first);
504 modest_pair_list_free (pair_list);
515 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
517 static ModestPairList*
518 get_transports (void)
520 GSList *transports = NULL;
522 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
523 GSList *accounts = modest_account_mgr_account_names (account_mgr,
524 TRUE /* only enabled accounts. */);
526 GSList *cursor = accounts;
528 gchar *account_name = cursor->data;
531 gchar *transport_account;
532 gboolean multi_mailbox = FALSE;
533 ModestProtocol *protocol = NULL;
535 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
537 transport_account = modest_account_mgr_get_server_account_name
538 (modest_runtime_get_account_mgr (),
540 TNY_ACCOUNT_TYPE_TRANSPORT);
541 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
542 ModestPairList *pair_list;
543 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
546 transports = g_slist_concat (transports, pair_list);
547 multi_mailbox = TRUE;
552 if (!multi_mailbox) {
553 gchar *from_string = NULL;
555 from_string = modest_account_mgr_get_from_string (account_mgr,
557 if (from_string && account_name) {
558 gchar *name = account_name;
559 ModestPair *pair = modest_pair_new ((gpointer) name,
560 (gpointer) from_string , TRUE);
561 transports = g_slist_prepend (transports, pair);
566 cursor = cursor->next;
568 g_slist_free (accounts); /* only free the accounts, not the elements,
569 * because they are used in the pairlist */
573 static void window_focus (GtkWindow *window,
577 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
581 scroll_drag_timeout (gpointer userdata)
583 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
584 ModestMsgEditWindowPrivate *priv;
586 /* It could happen that the window was already closed */
587 if (!GTK_WIDGET_VISIBLE (win))
590 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
592 correct_scroll_without_drag_check (win, TRUE);
594 priv->scroll_drag_timeout_id = 0;
600 correct_scroll_without_drag_check_idle (gpointer userdata)
602 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
603 ModestMsgEditWindowPrivate *priv;
605 GdkRectangle rectangle;
606 gint offset_min, offset_max;
610 /* It could happen that the window was already closed */
611 if (!GTK_WIDGET_VISIBLE (w))
614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
616 insert = gtk_text_buffer_get_insert (priv->text_buffer);
617 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
619 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
620 offset_min = priv->msg_body->allocation.y + rectangle.y;
621 offset_max = offset_min + rectangle.height;
623 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
624 offset_min = MAX (offset_min - 48, 0);
625 offset_max = MIN (offset_max + 48, vadj->upper);
627 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
629 priv->correct_scroll_idle = 0;
634 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
636 ModestMsgEditWindowPrivate *priv;
638 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
640 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
643 if (priv->correct_scroll_idle > 0) {
647 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
648 (GSourceFunc) correct_scroll_without_drag_check_idle,
654 correct_scroll (ModestMsgEditWindow *w)
656 ModestMsgEditWindowPrivate *priv;
658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
659 if (gtk_grab_get_current () == priv->msg_body) {
660 if (priv->scroll_drag_timeout_id == 0) {
661 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
663 (GSourceFunc) scroll_drag_timeout,
670 correct_scroll_without_drag_check (w, TRUE);
674 text_buffer_end_user_action (GtkTextBuffer *buffer,
675 ModestMsgEditWindow *userdata)
678 correct_scroll (userdata);
682 text_buffer_mark_set (GtkTextBuffer *buffer,
685 ModestMsgEditWindow *userdata)
687 gtk_text_buffer_begin_user_action (buffer);
688 gtk_text_buffer_end_user_action (buffer);
692 cut_clipboard_check (GtkTextView *text_view,
695 GtkTextBuffer *buffer;
697 buffer = gtk_text_view_get_buffer (text_view);
698 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
699 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
704 copy_clipboard_check (GtkTextView *text_view,
707 GtkTextBuffer *buffer;
709 buffer = gtk_text_view_get_buffer (text_view);
710 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
711 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
716 attachment_deleted (ModestAttachmentsView *attachments_view,
719 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
724 body_size_request (GtkWidget *body,
728 /* Make sure the body always get at least 70 pixels */
729 if (req->height < 70)
734 connect_signals (ModestMsgEditWindow *obj)
736 ModestMsgEditWindowPrivate *priv;
738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
740 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
741 G_CALLBACK (text_buffer_refresh_attributes), obj);
742 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
743 G_CALLBACK (text_buffer_can_undo), obj);
744 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
745 G_CALLBACK (text_buffer_can_redo), obj);
746 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
747 G_CALLBACK (body_changed), obj);
748 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
749 G_CALLBACK (body_insert_text), obj);
750 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
751 G_CALLBACK (body_changed), obj);
752 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
753 G_CALLBACK (text_buffer_end_user_action), obj);
754 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
755 G_CALLBACK (text_buffer_mark_set), obj);
756 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
757 G_CALLBACK (text_buffer_apply_tag), obj);
758 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
759 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
760 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
761 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
762 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
763 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
765 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
766 G_CALLBACK (modest_ui_actions_on_send), obj);
768 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
769 G_CALLBACK (from_field_changed), obj);
771 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
772 G_CALLBACK (msg_body_focus), obj);
773 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
774 G_CALLBACK (msg_body_focus), obj);
775 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
776 G_CALLBACK (body_size_request), obj);
777 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
778 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
779 "changed", G_CALLBACK (recpt_field_changed), obj);
780 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
781 "changed", G_CALLBACK (recpt_field_changed), obj);
782 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
783 "changed", G_CALLBACK (recpt_field_changed), obj);
784 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
785 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
786 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
788 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
789 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
791 priv->clipboard_change_handler_id =
792 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
793 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
794 priv->default_clipboard_change_handler_id =
795 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
796 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
798 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
799 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
800 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
804 init_wp_text_view_style ()
806 static gboolean initialized = FALSE;
809 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
815 init_window (ModestMsgEditWindow *obj)
817 GtkWidget *to_caption, *subject_caption;
818 GtkWidget *main_vbox;
819 ModestMsgEditWindowPrivate *priv;
820 GtkActionGroup *action_group;
821 ModestWindowPrivate *parent_priv;
822 GdkPixbuf *window_icon = NULL;
823 GError *error = NULL;
825 GtkSizeGroup *title_size_group;
826 GtkSizeGroup *value_size_group;
827 GtkWidget *window_box;
828 GtkWidget *window_align;
829 #if (GTK_MINOR_VERSION >= 10)
830 GdkAtom deserialize_type;
832 GtkWidget *from_send_hbox;
833 GtkWidget *send_icon;
834 GtkWidget *attachments_label;
835 GtkWidget *branding_box;
837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
838 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
840 parent_priv->ui_manager = gtk_ui_manager_new();
841 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
842 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
844 /* Add common actions */
845 gtk_action_group_add_actions (action_group,
846 modest_msg_edit_action_entries,
847 G_N_ELEMENTS (modest_msg_edit_action_entries),
849 gtk_action_group_add_actions (action_group,
850 hildon2_msg_edit_action_entries,
851 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
853 gtk_action_group_add_toggle_actions (action_group,
854 modest_msg_edit_toggle_action_entries,
855 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
857 gtk_action_group_add_radio_actions (action_group,
858 modest_msg_edit_alignment_radio_action_entries,
859 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
861 G_CALLBACK (modest_ui_actions_on_change_justify),
863 gtk_action_group_add_radio_actions (action_group,
864 modest_msg_edit_priority_action_entries,
865 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
867 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
869 gtk_action_group_add_radio_actions (action_group,
870 modest_msg_edit_file_format_action_entries,
871 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
872 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
873 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
875 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
876 g_object_unref (action_group);
878 /* Load the UI definition */
879 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
882 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
883 g_clear_error (&error);
886 /* Add accelerators */
887 gtk_window_add_accel_group (GTK_WINDOW (obj),
888 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
890 parent_priv->menubar = NULL;
892 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
893 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
895 /* Note: This ModestPairList* must exist for as long as the picker
896 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
897 * so it can't know how to manage its memory. */
898 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
899 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
901 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
902 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
903 _("mail_va_from"), priv->from_field);
904 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
905 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
906 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
908 priv->to_field = modest_recpt_editor_new ();
909 priv->cc_field = modest_recpt_editor_new ();
910 priv->bcc_field = modest_recpt_editor_new ();
911 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
912 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
913 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
914 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
915 priv->priority_icon = gtk_image_new ();
916 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
917 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
918 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
919 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
920 hildon_entry_set_placeholder ((HildonEntry *) priv->subject_field, _("mail_va_no_subject"));
921 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
922 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
923 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
924 priv->attachments_view = modest_attachments_view_new (NULL);
925 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
926 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
928 priv->header_box = gtk_vbox_new (FALSE, 0);
930 to_caption = _create_addressbook_box
931 (title_size_group, value_size_group,
932 _("mail_va_to"), priv->to_field);
933 priv->cc_caption = _create_addressbook_box
934 (title_size_group, value_size_group,
935 _("mail_va_cc"), priv->cc_field);
936 priv->bcc_caption = _create_addressbook_box
937 (title_size_group, value_size_group,
938 _("mail_va_hotfix1"), priv->bcc_field);
939 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
940 _("mail_va_subject"), FALSE, priv->subject_box);
941 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
942 _("mail_va_attachment"),
944 priv->attachments_view,
945 HILDON_SIZE_AUTO_WIDTH |
946 HILDON_SIZE_AUTO_HEIGHT);
947 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
948 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
951 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
952 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
953 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
954 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
956 g_object_unref (title_size_group);
957 g_object_unref (value_size_group);
959 priv->brand_icon = gtk_image_new ();
960 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
961 priv->brand_label = gtk_label_new (NULL);
962 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
963 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
964 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
965 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
967 from_send_hbox = gtk_hbox_new (FALSE, 0);
968 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
969 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
971 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
972 gtk_widget_show (branding_box);
973 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
974 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
976 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
977 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
978 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
979 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
982 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
983 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
984 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
985 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
986 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
987 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
988 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
989 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
991 init_wp_text_view_style ();
993 priv->msg_body = modest_wp_text_view_new ();
996 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
997 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
998 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
999 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1000 #if (GTK_MINOR_VERSION >= 10)
1001 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1002 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1004 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1005 deserialize_type, TRUE);
1007 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1009 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1010 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1012 priv->pannable = hildon_pannable_area_new ();
1014 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1016 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1017 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1018 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), MODEST_MARGIN_HALF, 0,
1019 MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1021 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1022 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1023 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1025 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1026 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1028 window_box = gtk_vbox_new (FALSE, 0);
1029 gtk_container_add (GTK_CONTAINER(obj), window_box);
1031 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1033 /* Set window icon */
1034 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1036 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1037 g_object_unref (window_icon);
1042 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1044 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1046 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1047 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1048 priv->clipboard_change_handler_id))
1049 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1050 priv->clipboard_change_handler_id);
1051 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1052 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1053 priv->default_clipboard_change_handler_id))
1054 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1055 priv->default_clipboard_change_handler_id);
1057 if (priv->account_removed_handler_id &&
1058 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1059 priv->account_removed_handler_id))
1060 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1061 priv->account_removed_handler_id);
1065 modest_msg_edit_window_finalize (GObject *obj)
1067 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1069 g_object_unref (priv->custom_header_pairs);
1071 if (priv->max_chars_banner) {
1072 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1073 priv->max_chars_banner = FALSE;
1076 /* Sanity check: shouldn't be needed, the window mgr should
1077 call this function before */
1078 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1080 if (priv->font_dialog != NULL) {
1081 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1084 if (priv->clipboard_text != NULL) {
1085 g_free (priv->clipboard_text);
1086 priv->clipboard_text = NULL;
1089 if (priv->draft_msg != NULL) {
1090 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1091 if (TNY_IS_HEADER (header)) {
1092 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1093 modest_window_mgr_unregister_header (mgr, header);
1095 g_object_unref (priv->draft_msg);
1096 priv->draft_msg = NULL;
1098 if (priv->outbox_msg != NULL) {
1099 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1100 if (TNY_IS_HEADER (header)) {
1101 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1102 modest_window_mgr_unregister_header (mgr, header);
1104 g_object_unref (priv->outbox_msg);
1105 priv->outbox_msg = NULL;
1107 if (priv->correct_scroll_idle > 0) {
1108 g_source_remove (priv->correct_scroll_idle);
1109 priv->correct_scroll_idle = 0;
1111 if (priv->scroll_drag_timeout_id > 0) {
1112 g_source_remove (priv->scroll_drag_timeout_id);
1113 priv->scroll_drag_timeout_id = 0;
1115 if (priv->clipboard_owner_idle > 0) {
1116 g_source_remove (priv->clipboard_owner_idle);
1117 priv->clipboard_owner_idle = 0;
1119 if (priv->original_account_name)
1120 g_free (priv->original_account_name);
1121 if (priv->original_mailbox)
1122 g_free (priv->original_mailbox);
1123 g_free (priv->msg_uid);
1124 g_free (priv->last_search);
1125 g_free (priv->references);
1126 g_free (priv->in_reply_to);
1127 g_object_unref (priv->attachments);
1128 g_object_unref (priv->images);
1130 /* This had to stay alive for as long as the picker that used it: */
1131 modest_pair_list_free (priv->from_field_protos);
1133 G_OBJECT_CLASS(parent_class)->finalize (obj);
1137 pixbuf_size_prepared (GdkPixbufLoader *loader,
1140 ModestMsgEditWindow *self)
1142 gint new_height, new_width;
1145 new_height = height;
1149 if (width > IMAGE_MAX_WIDTH) {
1150 new_height = height * IMAGE_MAX_WIDTH / width;
1151 new_width = IMAGE_MAX_WIDTH;
1154 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1158 pixbuf_from_stream (TnyStream *stream,
1159 const gchar *mime_type,
1160 guint64 *stream_size,
1161 ModestMsgEditWindow *self)
1163 GdkPixbufLoader *loader;
1166 GError *error = NULL;
1170 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1172 if (loader == NULL) {
1177 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1179 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1181 tny_stream_reset (TNY_STREAM (stream));
1182 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1183 unsigned char read_buffer[128];
1185 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1187 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1190 /* Allow some UI responsiveness */
1191 while (gtk_events_pending ())
1192 gtk_main_iteration ();
1194 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1196 gdk_pixbuf_loader_close (loader, &error);
1199 g_error_free (error);
1200 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1202 g_object_ref (pixbuf);
1203 g_object_unref (loader);
1208 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1209 GdkPixbuf *new_pixbuf;
1211 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1212 gdk_pixbuf_get_width (pixbuf);
1213 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1214 g_object_unref (pixbuf);
1215 pixbuf = new_pixbuf;
1219 *stream_size = size;
1225 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1227 ModestMsgEditWindowPrivate *priv;
1230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1232 g_object_ref (self);
1233 for (iter = tny_list_create_iterator (attachments);
1234 !tny_iterator_is_done (iter);
1235 tny_iterator_next (iter)) {
1236 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1237 const gchar *cid = tny_mime_part_get_content_id (part);
1238 const gchar *mime_type = tny_mime_part_get_content_type (part);
1239 if ((cid != NULL)&&(mime_type != NULL)) {
1240 guint64 stream_size;
1241 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1242 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1245 g_object_unref (stream);
1247 if (pixbuf != NULL) {
1248 priv->images_count ++;
1249 priv->images_size += stream_size;
1250 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1251 g_object_unref (pixbuf);
1254 g_object_unref (part);
1256 g_object_unref (iter);
1257 g_object_unref (self);
1261 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1263 TnyMimePart *parent = NULL;
1264 const gchar *content_type = NULL;
1265 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1267 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1269 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1270 parent = g_object_ref (msg);
1271 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1272 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1275 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1276 iter = tny_list_create_iterator (parts);
1277 while (!tny_iterator_is_done (iter)) {
1279 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1280 content_type = tny_mime_part_get_content_type (part);
1281 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1285 g_object_unref (part);
1287 tny_iterator_next (iter);
1289 g_object_unref (iter);
1290 g_object_unref (parts);
1293 if (parent != NULL) {
1294 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1297 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1298 iter = tny_list_create_iterator (parts);
1299 while (!tny_iterator_is_done (iter)) {
1301 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1302 content_type = tny_mime_part_get_content_type (part);
1303 if (content_type && g_str_has_prefix (content_type, "image/")) {
1304 tny_list_prepend (priv->images, (GObject *) part);
1306 g_object_unref (part);
1307 tny_iterator_next (iter);
1309 g_object_unref (iter);
1310 g_object_unref (parts);
1311 g_object_unref (parent);
1316 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1319 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1321 for (iter = tny_list_create_iterator (attachments) ;
1322 !tny_iterator_is_done (iter);
1323 tny_iterator_next (iter)) {
1324 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1325 const gchar *cid = tny_mime_part_get_content_id (part);
1327 char *invalid = NULL;
1328 gint int_cid = strtol (cid, &invalid, 10);
1329 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1330 priv->next_cid = int_cid + 1;
1333 g_object_unref (part);
1335 g_object_unref (iter);
1339 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1342 gchar *to, *cc, *bcc, *subject;
1344 ModestMsgEditWindowPrivate *priv;
1345 ModestWindowPrivate *parent_priv;
1347 TnyHeaderFlags priority_flags;
1348 TnyFolder *msg_folder;
1349 gboolean is_html = FALSE;
1350 gboolean field_view_set;
1351 TnyList *orig_header_pairs;
1353 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1354 g_return_if_fail (TNY_IS_MSG (msg));
1356 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1357 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1359 header = tny_msg_get_header (msg);
1360 to = tny_header_dup_to (header);
1361 cc = tny_header_dup_cc (header);
1362 bcc = tny_header_dup_bcc (header);
1363 subject = tny_header_dup_subject (header);
1365 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1366 priority_flags = tny_header_get_priority (header);
1369 gchar *quoted_names = modest_text_utils_quote_names (to);
1370 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1371 g_free (quoted_names);
1374 field_view_set = TRUE;
1376 gchar *quoted_names = modest_text_utils_quote_names (cc);
1377 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1378 g_free (quoted_names);
1379 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1380 gtk_widget_show (priv->cc_caption);
1381 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1382 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1383 gtk_widget_hide (priv->cc_caption);
1384 field_view_set = FALSE;
1386 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1388 field_view_set = TRUE;
1390 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1391 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1392 g_free (quoted_names);
1393 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1394 gtk_widget_show (priv->bcc_caption);
1395 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1396 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1397 gtk_widget_hide (priv->bcc_caption);
1398 field_view_set = FALSE;
1400 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1404 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1405 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1408 update_window_title (self);
1410 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1411 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1413 if ((body == NULL)||(body[0] == '\0')) {
1415 body = modest_text_utils_convert_to_html ("");
1418 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1419 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1422 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1425 /* Add attachments to the view */
1426 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1427 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1428 if (tny_list_get_length (priv->attachments) == 0) {
1429 gtk_widget_hide (priv->attachments_caption);
1431 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1432 gtk_widget_show_all (priv->attachments_caption);
1434 get_related_images (self, msg);
1435 update_next_cid (self, priv->attachments);
1436 update_next_cid (self, priv->images);
1437 replace_with_images (self, priv->images);
1439 if (preserve_is_rich && !is_html) {
1440 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1441 /* Get the default format required from configuration */
1442 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1443 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1446 /* Set the default focus depending on having already a To: field or not */
1447 if ((!to)||(*to == '\0')) {
1448 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1450 gtk_widget_grab_focus (priv->msg_body);
1453 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1455 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1456 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1458 modest_msg_edit_window_set_modified (self, FALSE);
1460 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1461 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1462 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1463 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1465 if (priv->msg_uid) {
1466 g_free (priv->msg_uid);
1467 priv->msg_uid = NULL;
1470 /* we should set a reference to the incoming message if it is a draft */
1471 msg_folder = tny_msg_get_folder (msg);
1473 if (modest_tny_folder_is_local_folder (msg_folder)) {
1474 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1475 if (type == TNY_FOLDER_TYPE_INVALID)
1476 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1478 if (type == TNY_FOLDER_TYPE_DRAFTS)
1479 priv->draft_msg = g_object_ref(msg);
1480 if (type == TNY_FOLDER_TYPE_OUTBOX)
1481 priv->outbox_msg = g_object_ref(msg);
1482 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1484 g_object_unref (msg_folder);
1487 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1488 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1489 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1490 g_object_unref (orig_header_pairs);
1499 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1501 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1502 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1503 GtkWidget *placeholder;
1504 GtkWidget *tool_item;
1509 GtkWidget *sizes_menu;
1510 GtkWidget *fonts_menu;
1516 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1517 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1518 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1519 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1521 /* Font color placeholder */
1522 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1523 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1526 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1527 priv->font_color_button = modest_color_button_new ();
1528 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1529 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1530 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1531 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1532 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1533 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1534 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1535 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1537 G_CALLBACK (modest_msg_edit_window_color_button_change),
1540 /* Font size and face placeholder */
1541 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1542 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1544 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1545 priv->size_tool_button_label = gtk_label_new (NULL);
1546 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1547 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1548 size_text, "</span>", NULL);
1549 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1550 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1552 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1553 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1554 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1555 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1556 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1557 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1558 gtk_widget_set_sensitive (arrow, FALSE);
1559 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1560 sizes_menu = gtk_menu_new ();
1561 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1562 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1565 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1566 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1568 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1572 if (wp_font_size[size_index] == 12)
1573 priv->current_size_index = size_index;
1577 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1578 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1579 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1580 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1581 priv->font_size_toolitem = tool_item;
1584 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1585 priv->font_tool_button_label = gtk_label_new (NULL);
1586 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1587 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1588 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1590 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1591 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1592 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1593 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1594 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1595 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1596 gtk_widget_set_sensitive (arrow, FALSE);
1597 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1598 fonts_menu = gtk_menu_new ();
1599 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1600 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1603 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1605 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1606 0, wp_get_font_name (font_index),
1609 if (font_index == DEFAULT_FONT)
1610 priv->current_face_index = font_index;
1612 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1613 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1614 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1615 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1616 priv->font_face_toolitem = tool_item;
1618 /* Set expand and homogeneous for remaining items */
1619 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1620 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1621 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1622 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1623 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1624 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1625 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1626 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1627 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1629 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1630 will not show the tool items added to the placeholders) */
1631 gtk_widget_show_all (parent_priv->toolbar);
1633 /* Set the no show all *after* showing all items. We do not
1634 want the toolbar to be shown with a show all because it
1635 could go against the gconf setting regarding showing or not
1636 the toolbar of the editor window */
1637 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1643 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1646 ModestWindowPrivate *parent_priv;
1647 ModestMsgEditWindowPrivate *priv;
1648 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1649 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1650 ModestWindowMgr *mgr = NULL;
1652 g_return_val_if_fail (msg, NULL);
1653 g_return_val_if_fail (account_name, NULL);
1655 mgr = modest_runtime_get_window_mgr ();
1657 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1659 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1660 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1662 /* Menubar. Update the state of some toggles */
1663 priv->from_field_protos = get_transports ();
1664 priv->original_mailbox = NULL;
1665 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1666 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 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1669 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1670 priv->original_mailbox = g_strdup (mailbox);
1671 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1672 /* We set the first mailbox as the active mailbox */
1673 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1674 if (priv->original_mailbox != NULL)
1675 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1676 (gpointer) priv->original_mailbox);
1678 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1679 (gpointer) account_name);
1681 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1683 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1684 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1685 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1687 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1688 hildon_touch_selector_get_current_text
1689 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1690 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1691 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1694 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1696 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1698 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1699 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1701 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1703 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1704 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1705 /* Add common dimming rules */
1706 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1707 modest_msg_edit_window_toolbar_dimming_entries,
1708 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1709 MODEST_WINDOW (obj));
1710 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1711 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1712 MODEST_WINDOW (obj));
1713 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1714 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1715 MODEST_WINDOW (obj));
1716 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1717 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1718 MODEST_WINDOW (obj));
1719 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1720 G_CALLBACK (modest_ui_dimming_rules_on_send),
1721 MODEST_WINDOW (obj));
1722 /* Insert dimming rules group for this window */
1723 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1724 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1726 /* Setup app menu */
1727 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1729 /* Checks the dimming rules */
1730 g_object_unref (toolbar_rules_group);
1731 g_object_unref (clipboard_rules_group);
1732 gtk_widget_hide (priv->priority_icon);
1733 gtk_widget_queue_resize (priv->subject_box);
1734 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1736 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1738 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1739 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1740 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1741 priv->update_caption_visibility = TRUE;
1743 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1745 /* Track account-removed signal, this window should be closed
1746 in the case we're creating a mail associated to the account
1748 priv->account_removed_handler_id =
1749 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1751 G_CALLBACK(on_account_removed),
1754 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1756 return (ModestWindow*) obj;
1760 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1762 GString **string_buffer = (GString **) user_data;
1764 *string_buffer = g_string_append (*string_buffer, buffer);
1770 * @result: A new string which should be freed with g_free().
1773 get_formatted_data (ModestMsgEditWindow *edit_window)
1775 ModestMsgEditWindowPrivate *priv;
1776 GString *string_buffer = g_string_new ("");
1778 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1780 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1782 modest_text_utils_hyperlinkify (string_buffer);
1784 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1786 return g_string_free (string_buffer, FALSE);
1791 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1794 const gchar *account_name;
1795 ModestMsgEditWindowPrivate *priv;
1796 TnyIterator *att_iter;
1797 const gchar *picker_active_id;
1799 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1801 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1803 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1804 g_return_val_if_fail (picker_active_id, NULL);
1805 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1807 /* don't free these (except from) */
1808 data = g_slice_new0 (MsgData);
1809 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1810 data->account_name = g_strdup (account_name);
1811 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1812 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1813 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1814 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1815 data->references = g_strdup (priv->references);
1816 data->in_reply_to = g_strdup (priv->in_reply_to);
1817 if (priv->draft_msg) {
1818 data->draft_msg = g_object_ref (priv->draft_msg);
1819 } else if (priv->outbox_msg) {
1820 data->draft_msg = g_object_ref (priv->outbox_msg);
1822 data->draft_msg = NULL;
1825 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1827 gtk_text_buffer_get_bounds (buf, &b, &e);
1828 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1830 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1831 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1833 data->html_body = NULL;
1835 /* deep-copy the data */
1836 att_iter = tny_list_create_iterator (priv->attachments);
1837 data->attachments = NULL;
1838 while (!tny_iterator_is_done (att_iter)) {
1839 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1840 if (!(TNY_IS_MIME_PART(part))) {
1841 g_warning ("strange data in attachment list");
1842 g_object_unref (part);
1843 tny_iterator_next (att_iter);
1846 data->attachments = g_list_append (data->attachments,
1848 tny_iterator_next (att_iter);
1850 g_object_unref (att_iter);
1852 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1853 att_iter = tny_list_create_iterator (priv->images);
1854 data->images = NULL;
1855 while (!tny_iterator_is_done (att_iter)) {
1856 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1858 if (!(TNY_IS_MIME_PART(part))) {
1859 g_warning ("strange data in attachment list");
1860 g_object_unref (part);
1861 tny_iterator_next (att_iter);
1864 cid = tny_mime_part_get_content_id (part);
1866 gchar *image_tag_id;
1867 GtkTextTag *image_tag;
1869 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1870 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1871 g_free (image_tag_id);
1873 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1875 ((gtk_text_iter_has_tag (&iter, image_tag))||
1876 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1877 data->images = g_list_append (data->images,
1878 g_object_ref (part));
1880 g_object_unref (part);
1881 tny_iterator_next (att_iter);
1883 g_object_unref (att_iter);
1885 data->priority_flags = priv->priority_flags;
1886 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
1893 unref_gobject (GObject *obj, gpointer data)
1895 if (!G_IS_OBJECT(obj))
1897 g_object_unref (obj);
1901 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1904 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1912 g_free (data->from);
1913 g_free (data->subject);
1914 g_free (data->plain_body);
1915 g_free (data->html_body);
1916 g_free (data->account_name);
1917 g_free (data->references);
1918 g_free (data->in_reply_to);
1920 g_object_unref (data->custom_header_pairs);
1922 if (data->draft_msg != NULL) {
1923 g_object_unref (data->draft_msg);
1924 data->draft_msg = NULL;
1927 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1928 g_list_free (data->attachments);
1929 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1930 g_list_free (data->images);
1932 g_slice_free (MsgData, data);
1936 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1938 guint64 *parts_size)
1940 ModestMsgEditWindowPrivate *priv;
1942 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1944 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1946 /* TODO: add images */
1947 *parts_size += priv->images_size;
1948 *parts_count += priv->images_count;
1953 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1956 ModestMsgEditWindowPrivate *priv = NULL;
1957 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1959 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1961 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1963 return MODEST_MSG_EDIT_FORMAT_HTML;
1965 return MODEST_MSG_EDIT_FORMAT_TEXT;
1969 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1970 ModestMsgEditFormat format)
1972 ModestMsgEditWindowPrivate *priv;
1973 ModestWindowPrivate *parent_priv;
1975 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1976 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1977 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1980 case MODEST_MSG_EDIT_FORMAT_HTML:
1981 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1982 update_signature (self, priv->last_from_account, priv->last_from_account);
1983 if (parent_priv->toolbar)
1984 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
1985 MODEST_MSG_EDIT_WINDOW (self));
1987 case MODEST_MSG_EDIT_FORMAT_TEXT:
1988 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1989 if (parent_priv->toolbar)
1990 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
1991 MODEST_MSG_EDIT_WINDOW (self));
1994 g_return_if_reached ();
1998 ModestMsgEditFormatState *
1999 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2001 ModestMsgEditFormatState *format_state = NULL;
2002 ModestMsgEditWindowPrivate *priv;
2003 WPTextBufferFormat *buffer_format;
2005 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2007 buffer_format = g_new0 (WPTextBufferFormat, 1);
2008 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2010 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2012 format_state = g_new0 (ModestMsgEditFormatState, 1);
2013 format_state->bold = buffer_format->bold&0x1;
2014 format_state->italics = buffer_format->italic&0x1;
2015 format_state->bullet = buffer_format->bullet&0x1;
2016 format_state->color = buffer_format->color;
2017 format_state->font_size = buffer_format->font_size;
2018 format_state->font_family = wp_get_font_name (buffer_format->font);
2019 format_state->justification = buffer_format->justification;
2020 g_free (buffer_format);
2022 return format_state;
2027 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2028 const ModestMsgEditFormatState *format_state)
2030 ModestMsgEditWindowPrivate *priv;
2031 WPTextBufferFormat *buffer_format;
2032 WPTextBufferFormat *current_format;
2034 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2035 g_return_if_fail (format_state != NULL);
2037 buffer_format = g_new0 (WPTextBufferFormat, 1);
2038 current_format = g_new0 (WPTextBufferFormat, 1);
2040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2041 gtk_widget_grab_focus (priv->msg_body);
2042 buffer_format->bold = (format_state->bold != FALSE);
2043 buffer_format->italic = (format_state->italics != FALSE);
2044 buffer_format->color = format_state->color;
2045 buffer_format->font_size = format_state->font_size;
2046 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2047 buffer_format->justification = format_state->justification;
2048 buffer_format->bullet = format_state->bullet;
2050 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2052 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2053 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2054 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2055 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2056 buffer_format->cs.font = (buffer_format->font != current_format->font);
2057 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2058 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2060 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2061 if (buffer_format->cs.bold) {
2062 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2063 GINT_TO_POINTER (buffer_format->bold&0x1));
2065 if (buffer_format->cs.italic) {
2066 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2067 GINT_TO_POINTER (buffer_format->italic&0x1));
2069 if (buffer_format->cs.color) {
2070 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2071 GINT_TO_POINTER (&(buffer_format->color)));
2073 if (buffer_format->cs.font_size) {
2074 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2075 GINT_TO_POINTER (buffer_format->font_size));
2077 if (buffer_format->cs.justification) {
2078 switch (buffer_format->justification) {
2079 case GTK_JUSTIFY_LEFT:
2080 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2081 GINT_TO_POINTER(TRUE));
2083 case GTK_JUSTIFY_CENTER:
2084 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2085 GINT_TO_POINTER(TRUE));
2087 case GTK_JUSTIFY_RIGHT:
2088 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2089 GINT_TO_POINTER(TRUE));
2096 if (buffer_format->cs.font) {
2097 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2098 GINT_TO_POINTER (buffer_format->font));
2100 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2101 if (buffer_format->cs.bullet) {
2102 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2103 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2105 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2107 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2109 g_free (buffer_format);
2110 g_free (current_format);
2112 /* Check dimming rules */
2113 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2114 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2118 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2120 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2122 ModestWindowPrivate *parent_priv;
2123 ModestMsgEditWindowPrivate *priv;
2125 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2126 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2128 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2129 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2130 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2131 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2133 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2134 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2135 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2138 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2140 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2141 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2143 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2144 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2146 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2147 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2150 switch (buffer_format->justification)
2152 case GTK_JUSTIFY_LEFT:
2153 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2155 case GTK_JUSTIFY_CENTER:
2156 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2158 case GTK_JUSTIFY_RIGHT:
2159 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2166 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2168 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2169 G_CALLBACK (modest_msg_edit_window_color_button_change),
2171 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2172 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2173 G_CALLBACK (modest_msg_edit_window_color_button_change),
2176 if (priv->current_size_index != buffer_format->font_size) {
2180 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2181 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2185 priv->current_size_index = buffer_format->font_size;
2187 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2188 markup = g_strconcat ("<span font_family='Sans'>",
2189 size_text, "</span>", NULL);
2191 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2195 gtk_tree_path_free (path);
2198 if (priv->current_face_index != buffer_format->font) {
2202 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2203 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2207 priv->current_face_index = buffer_format->font;
2208 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2209 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2210 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2217 g_free (buffer_format);
2223 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2225 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2226 ModestMsgEditWindowPrivate *priv;
2227 GtkWidget *dialog = NULL;
2229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2230 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2232 dialog = hildon_color_chooser_new ();
2233 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2234 g_free (buffer_format);
2236 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2238 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2239 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2242 gtk_widget_destroy (dialog);
2247 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2249 ModestMsgEditWindowPrivate *priv;
2250 GtkWidget *dialog = NULL;
2251 GdkColor *old_color = NULL;
2253 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2254 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2256 dialog = hildon_color_chooser_new ();
2257 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2259 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2261 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2262 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2264 gtk_widget_destroy (dialog);
2269 create_stream_for_uri (const gchar* uri)
2274 TnyStream *result = NULL;
2276 GnomeVFSHandle *handle = NULL;
2277 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2278 if (test == GNOME_VFS_OK) {
2279 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2280 /* Streams over OBEX (Bluetooth) are not seekable but
2281 * we expect them to be (we might need to read them
2282 * several times). So if this is a Bluetooth URI just
2283 * read the whole file into memory (this is not a fast
2284 * protocol so we can assume that these files are not
2285 * going to be very big) */
2286 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2287 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2288 TnyStream *memstream = tny_camel_mem_stream_new ();
2289 tny_stream_write_to_stream (vfssstream, memstream);
2290 g_object_unref (vfssstream);
2293 result = vfssstream;
2301 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2304 ModestMsgEditWindowPrivate *priv;
2305 GtkWidget *dialog = NULL;
2307 GSList *uris = NULL;
2308 GSList *uri_node = NULL;
2310 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2312 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2313 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2314 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2316 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2318 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2319 GTK_WINDOW (dialog), GTK_WINDOW (window));
2321 response = gtk_dialog_run (GTK_DIALOG (dialog));
2323 case GTK_RESPONSE_OK:
2325 gchar *current_folder;
2326 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2327 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2328 if (current_folder && current_folder != '\0') {
2330 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2331 current_folder, &err);
2333 g_debug ("Error storing latest used folder: %s", err->message);
2337 g_free (current_folder);
2343 gtk_widget_destroy (dialog);
2345 g_object_ref (window);
2346 /* The operation could take some time so allow the dialog to be closed */
2347 while (gtk_events_pending ())
2348 gtk_main_iteration ();
2350 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2352 GnomeVFSHandle *handle = NULL;
2353 GnomeVFSResult result;
2354 GtkTextIter position;
2355 GtkTextMark *insert_mark;
2357 uri = (const gchar *) uri_node->data;
2358 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2359 if (result == GNOME_VFS_OK) {
2361 GnomeVFSFileInfo *info;
2362 gchar *filename, *basename, *escaped_filename;
2363 TnyMimePart *mime_part;
2365 const gchar *mime_type = NULL;
2366 GnomeVFSURI *vfs_uri;
2367 guint64 stream_size;
2369 gnome_vfs_close (handle);
2370 vfs_uri = gnome_vfs_uri_new (uri);
2372 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2373 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2374 g_free (escaped_filename);
2375 gnome_vfs_uri_unref (vfs_uri);
2376 info = gnome_vfs_file_info_new ();
2378 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2379 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2381 mime_type = gnome_vfs_file_info_get_mime_type (info);
2383 mime_part = tny_platform_factory_new_mime_part
2384 (modest_runtime_get_platform_factory ());
2386 TnyStream *stream = create_stream_for_uri (uri);
2388 if (stream == NULL) {
2390 modest_platform_information_banner (NULL, NULL,
2391 _FM("sfil_ib_opening_not_allowed"));
2393 g_object_unref (mime_part);
2394 gnome_vfs_file_info_unref (info);
2398 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2400 content_id = g_strdup_printf ("%d", priv->next_cid);
2401 tny_mime_part_set_content_id (mime_part, content_id);
2402 g_free (content_id);
2405 basename = g_path_get_basename (filename);
2406 tny_mime_part_set_filename (mime_part, basename);
2409 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2411 if (pixbuf != NULL) {
2412 priv->images_size += stream_size;
2413 priv->images_count ++;
2414 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2415 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2416 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2417 tny_mime_part_get_content_id (mime_part), pixbuf);
2418 g_object_unref (pixbuf);
2420 tny_list_prepend (priv->images, (GObject *) mime_part);
2421 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2423 modest_platform_information_banner (NULL, NULL,
2424 _("mail_ib_file_operation_failed"));
2428 g_object_unref (mime_part);
2429 gnome_vfs_file_info_unref (info);
2433 g_object_unref (window);
2437 on_attach_file_response (GtkDialog *dialog,
2441 GSList *uris = NULL;
2443 GnomeVFSFileSize total_size, allowed_size;
2444 ModestMsgEditWindow *window;
2445 ModestMsgEditWindowPrivate *priv;
2450 case GTK_RESPONSE_OK:
2452 gchar *current_folder;
2454 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2455 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2456 if (current_folder && current_folder != '\0') {
2458 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2459 current_folder, &err);
2461 g_debug ("Error storing latest used folder: %s", err->message);
2465 g_free (current_folder);
2472 window = MODEST_MSG_EDIT_WINDOW (user_data);
2473 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2475 /* allowed size is the maximum size - what's already there */
2476 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2477 &att_num, &att_size);
2478 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2481 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2483 const gchar *uri = (const gchar *) uri_node->data;
2486 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2488 if (total_size > allowed_size) {
2489 g_debug ("%s: total size: %u",
2490 __FUNCTION__, (unsigned int)total_size);
2493 allowed_size -= total_size;
2495 g_slist_foreach (uris, (GFunc) g_free, NULL);
2496 g_slist_free (uris);
2498 gtk_widget_destroy (GTK_WIDGET (dialog));
2502 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2504 GtkWidget *dialog = NULL;
2505 ModestMsgEditWindowPrivate *priv;
2508 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2510 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2512 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2515 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2516 GTK_FILE_CHOOSER_ACTION_OPEN);
2517 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2518 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2519 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2520 if (conf_folder && conf_folder[0] != '\0') {
2521 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2524 /* Set the default folder to documents folder */
2525 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2528 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2529 ".documents", NULL);
2531 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2532 g_free (docs_folder);
2534 g_free (conf_folder);
2535 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2536 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2537 GTK_WINDOW (dialog), GTK_WINDOW (window));
2539 /* Connect to response & show */
2540 g_signal_connect (dialog, "response",
2541 G_CALLBACK (on_attach_file_response), window);
2542 gtk_widget_show (dialog);
2547 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2549 GnomeVFSFileSize allowed_size)
2552 GnomeVFSHandle *handle = NULL;
2553 ModestMsgEditWindowPrivate *priv;
2554 GnomeVFSResult result;
2555 GnomeVFSFileSize size = 0;
2556 g_return_val_if_fail (window, 0);
2557 g_return_val_if_fail (uri, 0);
2559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2561 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2562 if (result == GNOME_VFS_OK) {
2563 TnyMimePart *mime_part;
2565 const gchar *mime_type = NULL;
2567 gchar *escaped_filename;
2570 GnomeVFSFileInfo *info;
2571 GnomeVFSURI *vfs_uri;
2573 gnome_vfs_close (handle);
2574 vfs_uri = gnome_vfs_uri_new (uri);
2577 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2578 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2579 g_free (escaped_filename);
2580 gnome_vfs_uri_unref (vfs_uri);
2582 info = gnome_vfs_file_info_new ();
2584 if (gnome_vfs_get_file_info (uri,
2586 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2588 mime_type = gnome_vfs_file_info_get_mime_type (info);
2589 mime_part = tny_platform_factory_new_mime_part
2590 (modest_runtime_get_platform_factory ());
2592 /* try to get the attachment's size; this may fail for weird
2593 * file systems, like obex, upnp... */
2594 if (allowed_size != 0 &&
2595 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2597 if (size > allowed_size) {
2598 modest_platform_information_banner (NULL, NULL,
2599 _("mail_ib_error_attachment_size"));
2604 g_debug ("%s: could not get attachment size", __FUNCTION__);
2606 stream = create_stream_for_uri (uri);
2608 if (stream == NULL) {
2610 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2612 g_object_unref (mime_part);
2614 gnome_vfs_file_info_unref (info);
2618 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2619 g_object_unref (stream);
2621 content_id = g_strdup_printf ("%d", priv->next_cid);
2622 tny_mime_part_set_content_id (mime_part, content_id);
2623 g_free (content_id);
2626 basename = g_path_get_basename (filename);
2627 tny_mime_part_set_filename (mime_part, basename);
2630 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2631 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2633 info->size == 0, info->size);
2634 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2635 gtk_widget_show_all (priv->attachments_caption);
2636 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2638 g_object_unref (mime_part);
2639 gnome_vfs_file_info_unref (info);
2646 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2649 ModestMsgEditWindowPrivate *priv;
2652 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2653 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2655 if (att_list == NULL) {
2656 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2657 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2658 g_object_unref (att_list);
2662 g_object_ref (att_list);
2665 if (tny_list_get_length (att_list) == 0) {
2666 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2668 gboolean dialog_response;
2669 gchar *message = NULL;
2670 gchar *filename = NULL;
2672 if (tny_list_get_length (att_list) == 1) {
2674 iter = tny_list_create_iterator (att_list);
2675 part = (TnyMimePart *) tny_iterator_get_current (iter);
2676 g_object_unref (iter);
2677 if (TNY_IS_MSG (part)) {
2678 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2680 filename = tny_header_dup_subject (header);
2681 g_object_unref (header);
2683 if (filename == NULL) {
2684 filename = g_strdup (_("mail_va_no_subject"));
2687 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2689 g_object_unref (part);
2691 filename = g_strdup ("");
2693 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2694 "emev_nc_delete_attachments",
2695 tny_list_get_length (att_list)), filename);
2698 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2702 if (dialog_response != GTK_RESPONSE_OK) {
2703 g_object_unref (att_list);
2707 for (iter = tny_list_create_iterator (att_list);
2708 !tny_iterator_is_done (iter);
2709 tny_iterator_next (iter)) {
2710 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2711 const gchar *att_id;
2712 tny_list_remove (priv->attachments, (GObject *) mime_part);
2714 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2716 if (tny_list_get_length (priv->attachments) == 0)
2717 gtk_widget_hide (priv->attachments_caption);
2718 att_id = tny_mime_part_get_content_id (mime_part);
2720 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2722 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2723 g_object_unref (mime_part);
2725 g_object_unref (iter);
2728 g_object_unref (att_list);
2730 /* if the last attachment has been removed, focus the Subject: field */
2731 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2732 gtk_widget_grab_focus (priv->subject_field);
2736 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2739 ModestMsgEditWindowPrivate *priv;
2742 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2744 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &new_color);
2746 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2748 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2752 font_size_clicked (GtkToolButton *button,
2753 ModestMsgEditWindow *window)
2755 ModestMsgEditWindowPrivate *priv;
2756 GtkWidget *selector, *dialog;
2758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2760 selector = hildon_touch_selector_new ();
2761 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2762 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2764 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2765 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2766 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2768 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2772 WPTextBufferFormat format;
2774 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2776 memset (&format, 0, sizeof (format));
2777 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2779 format.cs.font_size = TRUE;
2780 format.cs.text_position = TRUE;
2781 format.cs.font = TRUE;
2782 format.font_size = new_index;
2783 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2785 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2786 GINT_TO_POINTER (new_index)))
2787 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2789 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2790 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2791 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2792 size_text, "</span>", NULL);
2794 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2798 gtk_widget_destroy (dialog);
2800 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2805 font_face_clicked (GtkToolButton *button,
2806 ModestMsgEditWindow *window)
2808 ModestMsgEditWindowPrivate *priv;
2809 GtkWidget *selector, *dialog;
2810 GtkCellRenderer *renderer;
2812 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2814 selector = hildon_touch_selector_new ();
2815 renderer = gtk_cell_renderer_text_new ();
2816 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2817 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2818 renderer, "family", 0, "text", 0, NULL);
2819 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2821 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2822 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2823 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2825 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2826 gint new_font_index;
2830 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2831 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2832 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2836 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2838 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2839 GINT_TO_POINTER(new_font_index)))
2840 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2842 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2843 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2845 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2849 gtk_tree_path_free (path);
2852 gtk_widget_destroy (dialog);
2854 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2859 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2862 ModestMsgEditWindowPrivate *priv = NULL;
2863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2865 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2866 if (!priv->update_caption_visibility)
2869 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2871 gtk_widget_show (priv->cc_caption);
2873 gtk_widget_hide (priv->cc_caption);
2875 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2879 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2882 ModestMsgEditWindowPrivate *priv = NULL;
2883 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2886 if (!priv->update_caption_visibility)
2889 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2891 gtk_widget_show (priv->bcc_caption);
2893 gtk_widget_hide (priv->bcc_caption);
2895 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2899 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2900 ModestRecptEditor *editor)
2902 ModestMsgEditWindowPrivate *priv;
2904 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2905 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2907 /* we check for low-mem; in that case, show a warning, and don't allow
2908 * for the addressbook
2910 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2913 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2915 if (editor == NULL) {
2916 GtkWidget *view_focus, *parent;
2917 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2919 /* This code should be kept in sync with ModestRecptEditor. The
2920 textview inside the recpt editor is the one that really gets the
2921 focus. As it's inside a scrolled window, and this one inside the
2922 hbox recpt editor inherits from, we'll need to go up in the
2923 hierarchy to know if the text view is part of the recpt editor
2924 or if it's a different text entry */
2925 parent = gtk_widget_get_parent (view_focus);
2926 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2927 editor = MODEST_RECPT_EDITOR (parent);
2930 editor = MODEST_RECPT_EDITOR (priv->to_field);
2933 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2937 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2939 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2941 modest_msg_edit_window_open_addressbook (window, NULL);
2945 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2946 gboolean show_toolbar)
2948 ModestWindowPrivate *parent_priv;
2949 ModestMsgEditWindowPrivate *priv;
2951 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2952 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2953 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2955 /* We can not just use the code of
2956 modest_msg_edit_window_setup_toolbar because it has a
2957 mixture of both initialization and creation code. */
2959 gint current_format;
2960 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2961 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2962 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2963 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2965 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2968 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2970 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
2971 if (hildon_check_button_get_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button)) != show_toolbar) {
2972 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button), show_toolbar);
2977 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2978 TnyHeaderFlags priority_flags)
2980 ModestMsgEditWindowPrivate *priv;
2981 ModestWindowPrivate *parent_priv;
2983 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2985 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2986 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2988 if (priv->priority_flags != priority_flags) {
2989 GtkAction *priority_action = NULL;
2991 priv->priority_flags = priority_flags;
2993 switch (priority_flags) {
2994 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2995 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2996 MODEST_HEADER_ICON_HIGH,
2997 HILDON_ICON_SIZE_SMALL);
2998 gtk_widget_show (priv->priority_icon);
2999 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3000 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3002 case TNY_HEADER_FLAG_LOW_PRIORITY:
3003 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3004 MODEST_HEADER_ICON_LOW,
3005 HILDON_ICON_SIZE_SMALL);
3006 gtk_widget_show (priv->priority_icon);
3007 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3008 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3011 gtk_widget_hide (priv->priority_icon);
3012 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3013 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3016 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3017 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3019 gtk_widget_queue_resize (priv->subject_box);
3023 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3026 ModestMsgEditWindowPrivate *priv;
3027 ModestWindowPrivate *parent_priv;
3028 gint current_format;
3030 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3032 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3035 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3036 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3038 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3040 if (current_format != file_format) {
3041 switch (file_format) {
3042 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3043 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3044 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3045 update_signature (window, priv->last_from_account, priv->last_from_account);
3046 if (parent_priv->toolbar)
3047 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3048 MODEST_MSG_EDIT_WINDOW (window));
3050 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3054 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3055 response = gtk_dialog_run (GTK_DIALOG (dialog));
3056 gtk_widget_destroy (dialog);
3057 if (response == GTK_RESPONSE_OK) {
3058 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3059 if (parent_priv->toolbar)
3060 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3061 MODEST_MSG_EDIT_WINDOW (window));
3063 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3064 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3069 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3070 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3071 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3076 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3079 ModestMsgEditWindowPrivate *priv;
3080 WPTextBufferFormat oldfmt, fmt;
3081 gint old_position = 0;
3085 GdkColor *color = NULL;
3086 gboolean bold, bold_set, italic, italic_set;
3087 gboolean underline, underline_set;
3088 gboolean strikethrough, strikethrough_set;
3089 gboolean position_set;
3090 gboolean font_size_set, font_set, color_set;
3093 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3094 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3096 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3097 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3098 GTK_WINDOW(dialog), GTK_WINDOW (window));
3100 /* First we get the currently selected font information */
3101 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3103 switch (oldfmt.text_position) {
3104 case TEXT_POSITION_NORMAL:
3107 case TEXT_POSITION_SUPERSCRIPT:
3115 g_object_set (G_OBJECT (dialog),
3116 "bold", oldfmt.bold != FALSE,
3117 "bold-set", !oldfmt.cs.bold,
3118 "underline", oldfmt.underline != FALSE,
3119 "underline-set", !oldfmt.cs.underline,
3120 "italic", oldfmt.italic != FALSE,
3121 "italic-set", !oldfmt.cs.italic,
3122 "strikethrough", oldfmt.strikethrough != FALSE,
3123 "strikethrough-set", !oldfmt.cs.strikethrough,
3124 "color", &oldfmt.color,
3125 "color-set", !oldfmt.cs.color,
3126 "size", wp_font_size[oldfmt.font_size],
3127 "size-set", !oldfmt.cs.font_size,
3128 "position", old_position,
3129 "position-set", !oldfmt.cs.text_position,
3130 "family", wp_get_font_name (oldfmt.font),
3131 "family-set", !oldfmt.cs.font,
3134 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3135 GTK_WINDOW (dialog), GTK_WINDOW (window));
3136 gtk_widget_show_all (dialog);
3137 priv->font_dialog = dialog;
3138 response = gtk_dialog_run (GTK_DIALOG (dialog));
3139 priv->font_dialog = NULL;
3140 if (response == GTK_RESPONSE_OK) {
3142 g_object_get( dialog,
3144 "bold-set", &bold_set,
3145 "underline", &underline,
3146 "underline-set", &underline_set,
3148 "italic-set", &italic_set,
3149 "strikethrough", &strikethrough,
3150 "strikethrough-set", &strikethrough_set,
3152 "color-set", &color_set,
3154 "size-set", &font_size_set,
3155 "family", &font_name,
3156 "family-set", &font_set,
3157 "position", &position,
3158 "position-set", &position_set,
3163 if (response == GTK_RESPONSE_OK) {
3164 memset(&fmt, 0, sizeof(fmt));
3170 fmt.italic = italic;
3171 fmt.cs.italic = TRUE;
3173 if (underline_set) {
3174 fmt.underline = underline;
3175 fmt.cs.underline = TRUE;
3177 if (strikethrough_set) {
3178 fmt.strikethrough = strikethrough;
3179 fmt.cs.strikethrough = TRUE;
3184 ? TEXT_POSITION_NORMAL
3185 : ( ( position == 1 )
3186 ? TEXT_POSITION_SUPERSCRIPT
3187 : TEXT_POSITION_SUBSCRIPT );
3188 fmt.cs.text_position = TRUE;
3189 fmt.font_size = oldfmt.font_size;
3193 fmt.cs.color = TRUE;
3196 fmt.font = wp_get_font_index(font_name,
3201 if (font_size_set) {
3202 fmt.cs.font_size = TRUE;
3203 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3205 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3206 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3208 gtk_widget_destroy (dialog);
3210 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3214 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3216 ModestMsgEditWindowPrivate *priv;
3217 ModestWindowPrivate *parent_priv;
3218 gboolean was_rich_text, is_rich_text;
3220 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3221 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3222 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3224 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3226 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3228 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3230 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3231 on_show_toolbar_button_toggled (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
3232 MODEST_MSG_EDIT_WINDOW (window));
3235 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3236 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3240 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3242 ModestMsgEditWindowPrivate *priv;
3244 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3245 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3247 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3249 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3250 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3255 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3257 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3259 priv->can_undo = can_undo;
3263 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3265 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3267 priv->can_redo = can_redo;
3271 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3273 ModestMsgEditWindowPrivate *priv;
3274 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3275 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 return priv->can_undo;
3281 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3283 ModestMsgEditWindowPrivate *priv;
3284 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3287 return priv->can_redo;
3292 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3295 GtkTextIter match_start, match_end;
3297 if (image_id == NULL)
3300 gtk_text_buffer_get_start_iter (buffer, &iter);
3302 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3303 GSList *tags = gtk_text_iter_get_tags (&match_start);
3305 for (node = tags; node != NULL; node = g_slist_next (node)) {
3306 GtkTextTag *tag = (GtkTextTag *) node->data;
3307 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3308 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3309 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3311 offset = gtk_text_iter_get_offset (&match_start);
3312 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3313 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3317 gtk_text_iter_forward_char (&iter);
3322 message_is_empty (ModestMsgEditWindow *window)
3324 ModestMsgEditWindowPrivate *priv = NULL;
3326 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3327 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3329 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3330 * so we can ignore markup.
3332 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3335 count = gtk_text_buffer_get_char_count (buf);
3341 msg_body_focus (GtkWidget *focus,
3342 GdkEventFocus *event,
3346 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3347 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3348 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3353 recpt_field_changed (GtkTextBuffer *buffer,
3354 ModestMsgEditWindow *editor)
3356 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3357 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3361 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3363 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3364 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3368 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3371 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3372 GtkTextBuffer *buffer;
3374 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3375 gtk_text_buffer_set_modified (buffer, modified);
3376 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3377 gtk_text_buffer_set_modified (buffer, modified);
3378 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3379 gtk_text_buffer_set_modified (buffer, modified);
3380 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3384 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3386 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3387 const char *account_name;
3388 GtkTextBuffer *buffer;
3390 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3391 if (gtk_text_buffer_get_modified (buffer))
3393 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3394 if (gtk_text_buffer_get_modified (buffer))
3396 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3397 if (gtk_text_buffer_get_modified (buffer))
3399 if (gtk_text_buffer_get_modified (priv->text_buffer))
3402 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3403 if (priv->original_mailbox) {
3404 if (!account_name || strcmp (account_name, priv->original_mailbox))
3406 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3417 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3419 ModestMsgEditWindowPrivate *priv = NULL;
3420 GSList *address_list = NULL;
3421 gboolean no_to, no_cc, no_bcc;
3423 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3424 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3426 /* check if there's no recipient added */
3427 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3428 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3429 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3432 if (no_to && no_cc && no_bcc) {
3433 /* no recipient contents, then select contacts */
3434 modest_msg_edit_window_open_addressbook (window, NULL);
3439 g_object_ref (window);
3440 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3441 (add_to_addressbook) ? &address_list : NULL)) {
3442 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3443 g_object_unref (window);
3446 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3447 (add_to_addressbook) ? &address_list : NULL)) {
3448 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3449 g_object_unref (window);
3452 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3453 (add_to_addressbook) ? &address_list : NULL)) {
3454 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3455 g_object_unref (window);
3459 /* Add contacts to address book */
3460 if (add_to_addressbook && address_list)
3461 modest_address_book_add_address_list (address_list);
3463 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3464 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3465 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3466 g_object_unref (window);
3473 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3475 GSList *recipients = NULL;
3476 ModestMsgEditWindowPrivate *priv;
3477 gchar *joined, *after_remove, *to, *cc, *bcc;
3479 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3481 /* First of all check names */
3482 if (!modest_msg_edit_window_check_names (self, FALSE))
3485 if (!modest_msg_edit_window_has_pending_addresses (self))
3488 /* Don't add the from obviously */
3489 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3490 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3491 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3493 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3498 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3501 recipients = modest_text_utils_split_addresses_list (after_remove);
3502 g_free (after_remove);
3505 /* Offer the user to add recipients to the address book */
3506 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3507 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3512 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3513 ModestMsgEditWindow *window)
3515 modest_msg_edit_window_offer_attach_file (window);
3519 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3521 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3523 return priv->clipboard_text;
3527 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3529 ModestMsgEditWindow *window)
3531 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3532 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3535 /* It could happen that the window was already closed */
3536 if (!GTK_WIDGET_VISIBLE (window))
3539 g_object_ref (window);
3540 text = gtk_clipboard_wait_for_text (selection_clipboard);
3542 if (priv->clipboard_text != NULL) {
3543 g_free (priv->clipboard_text);
3545 priv->clipboard_text = text;
3547 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3549 g_object_unref (window);
3552 static gboolean clipboard_owner_change_idle (gpointer userdata)
3554 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3555 ModestMsgEditWindowPrivate *priv;
3557 gdk_threads_enter ();
3558 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3559 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3561 priv->clipboard_owner_idle = 0;
3562 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3563 gdk_threads_leave ();
3569 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3571 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3572 if (priv->clipboard_owner_idle == 0) {
3573 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3574 clipboard_owner_change_idle,
3575 g_object_ref (window),
3581 subject_field_move_cursor (GtkEntry *entry,
3582 GtkMovementStep step,
3587 /* It could happen that the window was already closed */
3588 if (!GTK_WIDGET_VISIBLE (window))
3591 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3595 update_window_title (ModestMsgEditWindow *window)
3597 ModestMsgEditWindowPrivate *priv = NULL;
3598 const gchar *subject;
3600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3601 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3602 if (subject == NULL || subject[0] == '\0')
3603 subject = _("mail_va_new_email");
3605 gtk_window_set_title (GTK_WINDOW (window), subject);
3611 body_insert_text (GtkTextBuffer *buffer,
3612 GtkTextIter *location,
3615 ModestMsgEditWindow *window)
3617 GtkTextIter end_iter;
3624 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3626 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3628 offset = gtk_text_iter_get_offset (&end_iter);
3629 line = gtk_text_iter_get_line (&end_iter);
3633 while (text_offset < text + len) {
3634 if (*text_offset == '\n')
3636 if (text_lines + line >= MAX_BODY_LINES) {
3637 len = text_offset - text;
3643 utf8_len = g_utf8_strlen (text, len);
3645 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3646 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3647 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3652 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3654 /* Prevent endless recursion */
3655 result = g_strndup (text, utf8_end - text);
3656 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3657 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3658 (gpointer) result, (gpointer) (utf8_end - text),
3660 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3664 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3665 if (priv->max_chars_banner == NULL) {
3666 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3667 _CS("ckdg_ib_maximum_characters_reached"));
3668 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3674 subject_field_changed (GtkEditable *editable,
3675 ModestMsgEditWindow *window)
3677 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3678 update_window_title (window);
3679 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3680 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3681 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3684 subject_field_insert_text (GtkEditable *editable,
3686 gint new_text_length,
3688 ModestMsgEditWindow *window)
3690 GString *result = g_string_new ("");
3692 gint result_len = 0;
3693 const gchar *entry_text = NULL;
3696 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3697 old_length = g_utf8_strlen (entry_text, -1);
3699 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3700 gunichar c = g_utf8_get_char_validated (current, 8);
3701 /* Invalid unichar, stop */
3707 result = g_string_append_unichar (result, c);
3711 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3712 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3715 /* Prevent endless recursion */
3716 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3717 g_signal_emit_by_name (editable, "insert-text",
3718 (gpointer) result->str, (gpointer) result->len,
3719 (gpointer) position, (gpointer) window);
3720 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3724 if (result_len + old_length > 1000) {
3725 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3726 _CS("ckdg_ib_maximum_characters_reached"));
3728 g_string_free (result, TRUE);
3732 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3735 ModestMsgEditWindowPrivate *priv = NULL;
3737 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3740 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3743 gtk_widget_show_all (priv->find_toolbar);
3744 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3746 gtk_widget_hide_all (priv->find_toolbar);
3747 gtk_widget_grab_focus (priv->msg_body);
3752 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3754 GtkTextIter *match_start,
3755 GtkTextIter *match_end)
3757 GtkTextIter end_iter;
3758 gchar *str_casefold;
3761 gchar *range_casefold;
3764 gboolean result = FALSE;
3771 gtk_text_iter_forward_to_end (&end_iter);
3773 str_casefold = g_utf8_casefold (str, -1);
3774 str_chars_n = strlen (str);
3776 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3777 range_casefold = g_utf8_casefold (range_text, -1);
3778 range_chars_n = strlen (range_casefold);
3780 if (range_chars_n < str_chars_n) {
3781 g_free (str_casefold);
3782 g_free (range_text);
3783 g_free (range_casefold);
3787 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3788 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3789 if (!g_utf8_collate (range_subtext, str_casefold)) {
3790 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3792 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3793 match_start, match_end, NULL)) {
3794 g_debug ("Matched string with collate, but not matched in model");
3796 g_free (found_text);
3798 g_free (range_subtext);
3802 g_free (str_casefold);
3803 g_free (range_text);
3804 g_free (range_casefold);
3811 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3812 ModestMsgEditWindow *window)
3814 gchar *current_search = NULL;
3815 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3817 GtkTextIter selection_start, selection_end;
3818 GtkTextIter match_start, match_end;
3819 gboolean continue_search = FALSE;
3821 if (message_is_empty (window)) {
3822 g_free (priv->last_search);
3823 priv->last_search = NULL;
3824 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3828 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3829 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3830 g_free (current_search);
3831 g_free (priv->last_search);
3832 priv->last_search = NULL;
3833 /* Information banner about empty search */
3834 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3838 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3839 continue_search = TRUE;
3841 g_free (priv->last_search);
3842 priv->last_search = g_strdup (current_search);
3845 if (continue_search) {
3846 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3847 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3848 &match_start, &match_end);
3850 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3852 GtkTextIter buffer_start;
3853 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3854 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3855 &match_start, &match_end);
3857 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3860 /* Mark as selected the string found in search */
3862 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3863 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3864 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3866 g_free (priv->last_search);
3867 priv->last_search = NULL;
3869 g_free (current_search);
3873 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3875 ModestMsgEditWindowPrivate *priv;
3877 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3882 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3885 ModestMsgEditWindowPrivate *priv;
3887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3892 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3893 ModestMsgEditWindow *window)
3895 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3899 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3902 ModestMsgEditWindowPrivate *priv;
3903 TnyHeader *header = NULL;
3905 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3906 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3908 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3910 if (priv->draft_msg != NULL) {
3911 g_object_unref (priv->draft_msg);
3914 if (draft != NULL) {
3915 g_object_ref (draft);
3916 header = tny_msg_get_header (draft);
3917 if (priv->msg_uid) {
3918 g_free (priv->msg_uid);
3919 priv->msg_uid = NULL;
3921 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3924 priv->draft_msg = draft;
3928 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3929 GtkTextIter *start, GtkTextIter *end,
3932 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3933 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3936 if (tag == NULL) return;
3937 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3938 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3939 replace_with_images (window, priv->images);
3944 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3947 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3949 g_return_if_fail (TNY_IS_MIME_PART (part));
3950 tny_list_prepend (priv->attachments, (GObject *) part);
3951 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3952 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3953 gtk_widget_show_all (priv->attachments_caption);
3954 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3958 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3960 ModestMsgEditWindowPrivate *priv;
3962 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3963 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3965 return priv->msg_uid;
3969 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3970 ModestMsgEditWindowWidgetType widget_type)
3972 ModestMsgEditWindowPrivate *priv;
3974 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3975 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3977 switch (widget_type) {
3978 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3979 return priv->msg_body;
3981 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3982 return priv->to_field;
3984 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3985 return priv->cc_field;
3987 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3988 return priv->bcc_field;
3990 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3991 return priv->subject_field;
3993 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3994 return priv->attachments_view;
4002 remove_tags (WPTextBuffer *buffer)
4004 GtkTextIter start, end;
4006 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4007 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4009 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4013 on_account_removed (TnyAccountStore *account_store,
4014 TnyAccount *account,
4017 /* Do nothing if it's a store account, because we use the
4018 transport to send the messages */
4019 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4020 const gchar *parent_acc = NULL;
4021 const gchar *our_acc = NULL;
4023 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4024 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4025 /* Close this window if I'm showing a message of the removed account */
4026 if (strcmp (parent_acc, our_acc) == 0)
4027 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4032 update_signature (ModestMsgEditWindow *self,
4033 const gchar *old_account,
4034 const gchar *new_account)
4036 ModestMsgEditWindowPrivate *priv;
4037 gboolean has_old_signature, has_new_signature;
4039 ModestAccountMgr *mgr;
4042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4044 gtk_text_buffer_begin_user_action (priv->text_buffer);
4046 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4047 mgr = modest_runtime_get_account_mgr ();
4051 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4052 if (has_old_signature) {
4053 GtkTextIter match_start, match_end;
4055 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4056 seems that the search has some problems
4057 with the blank space at the end */
4058 if (gtk_text_iter_forward_search (&iter, "--",
4059 GTK_TEXT_SEARCH_TEXT_ONLY,
4060 &match_start, NULL, NULL)) {
4061 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4062 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4064 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4065 &match_start, &match_end, NULL)) {
4069 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4074 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4075 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4076 if (has_new_signature) {
4079 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4080 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4082 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4084 WPTextBufferFormat *fmt;
4085 GdkColor style_color;
4086 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4087 gdk_color_parse ("grey", &style_color);
4089 fmt = g_new0 (WPTextBufferFormat, 1);
4090 fmt->color = style_color;
4091 fmt->cs.color = 0x1;
4092 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4096 g_free (full_signature);
4098 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4102 gtk_text_buffer_end_user_action (priv->text_buffer);
4105 static void update_branding (ModestMsgEditWindow *self,
4106 const gchar *new_account)
4108 ModestMsgEditWindowPrivate *priv;
4109 ModestAccountMgr *mgr;
4110 const GdkPixbuf *new_icon = NULL;
4111 gchar *new_label = NULL;
4112 gboolean show = FALSE;
4114 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4116 mgr = modest_runtime_get_account_mgr ();
4118 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4120 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4121 gtk_widget_show (priv->brand_icon);
4124 gtk_widget_hide (priv->brand_icon);
4127 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4128 gtk_widget_show (priv->brand_label);
4132 gtk_widget_hide (priv->brand_label);
4136 gtk_widget_show (priv->brand_container);
4138 gtk_widget_hide (priv->brand_container);
4142 from_field_changed (HildonPickerButton *button,
4143 ModestMsgEditWindow *self)
4145 ModestMsgEditWindowPrivate *priv;
4146 gchar *old_account, *new_account;
4148 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4150 old_account = priv->last_from_account;
4151 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4154 g_warning ("%s, could not get the new account", __FUNCTION__);
4158 /* If the From is the same do nothing */
4159 if (old_account && new_account && !strcmp (old_account, new_account))
4162 priv->last_from_account = new_account;
4164 update_signature (self, old_account, new_account);
4165 update_branding (self, new_account);
4169 typedef struct _MessageSettingsHelper {
4170 ModestMsgEditWindow *window;
4171 GSList *priority_group;
4172 GSList *format_group;
4173 GtkToggleButton *current_priority;
4174 GtkToggleButton *current_format;
4175 } MessageSettingsHelper;
4178 on_priority_toggle (GtkToggleButton *button,
4179 MessageSettingsHelper *helper)
4182 ModestMsgEditWindowPrivate *priv;
4184 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4185 if (gtk_toggle_button_get_active (button)) {
4187 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4188 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4189 if ((node_button != button) &&
4190 gtk_toggle_button_get_active (node_button)) {
4191 gtk_toggle_button_set_active (node_button, FALSE);
4194 helper->current_priority = button;
4196 gboolean found = FALSE;
4197 /* If no one is active, activate it again */
4198 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4199 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4200 if (gtk_toggle_button_get_active (node_button)) {
4206 gtk_toggle_button_set_active (button, TRUE);
4212 on_format_toggle (GtkToggleButton *button,
4213 MessageSettingsHelper *helper)
4216 ModestMsgEditWindowPrivate *priv;
4218 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4219 if (gtk_toggle_button_get_active (button)) {
4221 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4222 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4223 if ((node_button != button) &&
4224 gtk_toggle_button_get_active (node_button)) {
4225 gtk_toggle_button_set_active (node_button, FALSE);
4228 helper->current_format = button;
4230 gboolean found = FALSE;
4231 /* If no one is active, activate it again */
4232 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4233 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4234 if (gtk_toggle_button_get_active (node_button)) {
4240 gtk_toggle_button_set_active (button, TRUE);
4247 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4252 GtkWidget *priority_hbox;
4253 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4254 GtkWidget *captioned;
4255 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4256 GtkWidget *format_hbox;
4257 GtkWidget *html_toggle, *text_toggle;
4258 ModestMsgEditWindowPrivate *priv;
4259 MessageSettingsHelper helper = {0,};
4261 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4263 helper.window = window;
4264 helper.priority_group = NULL;
4265 helper.format_group = NULL;
4267 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4268 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4270 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4271 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4272 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4273 vbox = gtk_vbox_new (FALSE, 0);
4274 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4275 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4276 gtk_container_add (GTK_CONTAINER (align), vbox);
4277 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4278 gtk_widget_show (align);
4279 gtk_widget_show (vbox);
4281 /* Priority toggles */
4282 priority_hbox = gtk_hbox_new (TRUE, 0);
4283 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4284 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4285 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4286 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4287 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4288 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4289 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4290 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4291 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4292 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4293 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4294 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4295 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4296 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4297 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4298 gtk_widget_show_all (priority_hbox);
4299 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4300 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4301 gtk_widget_show (captioned);
4302 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4304 /* format toggles */
4305 format_hbox = gtk_hbox_new (TRUE, 0);
4306 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4307 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4308 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4309 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4310 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4311 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4312 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4313 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4314 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4315 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4316 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4317 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4318 gtk_widget_show_all (format_hbox);
4319 gtk_widget_show (format_hbox);
4320 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4323 g_object_unref (title_sizegroup);
4324 g_object_unref (value_sizegroup);
4326 /* Set current values */
4327 switch (priv->priority_flags) {
4328 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4329 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4330 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4332 case TNY_HEADER_FLAG_LOW_PRIORITY:
4333 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4334 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4337 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4338 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4342 switch (modest_msg_edit_window_get_format (window)) {
4343 case MODEST_MSG_EDIT_FORMAT_TEXT:
4344 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4345 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4347 case MODEST_MSG_EDIT_FORMAT_HTML:
4349 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4350 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4354 /* Signal connects */
4355 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4356 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4357 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4358 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4359 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4361 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4362 GTK_WINDOW (dialog), GTK_WINDOW (window));
4364 /* Save settings if the user clicked on done */
4365 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4366 TnyHeaderFlags flags;
4367 ModestMsgEditFormat old_format, new_format;
4369 /* Set priority flags */
4370 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4371 if (priv->priority_flags != flags)
4372 modest_msg_edit_window_set_priority_flags (window, flags);
4374 /* Set edit format */
4375 old_format = modest_msg_edit_window_get_format (window);
4376 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4377 if (old_format != new_format) {
4378 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4379 modest_msg_edit_window_set_file_format (window, file_format);
4383 gtk_widget_destroy (dialog);
4384 g_slist_free (helper.priority_group);
4388 on_message_settings (GtkAction *action,
4389 ModestMsgEditWindow *window)
4391 modest_msg_edit_window_show_msg_settings_dialog (window);
4395 on_show_toolbar_button_toggled (HildonCheckButton *button,
4396 ModestMsgEditWindow *window)
4398 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4400 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4401 hildon_check_button_get_active (button));
4405 on_cc_button_toggled (HildonCheckButton *button,
4406 ModestMsgEditWindow *window)
4408 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4410 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4411 hildon_check_button_get_active (button));
4415 on_bcc_button_toggled (HildonCheckButton *button,
4416 ModestMsgEditWindow *window)
4418 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4420 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4421 hildon_check_button_get_active (button));
4425 setup_menu (ModestMsgEditWindow *self)
4427 ModestMsgEditWindowPrivate *priv = NULL;
4429 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4431 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4433 /* Settings menu buttons */
4434 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4435 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4437 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4438 APP_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4439 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4440 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4441 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4442 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4444 priv->cc_button = hildon_check_button_new (0);
4445 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4446 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4448 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4450 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4451 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4452 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4453 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4455 priv->bcc_button = hildon_check_button_new (0);
4456 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4457 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4459 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4461 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4462 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4463 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4464 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4466 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4467 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4469 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4470 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4471 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4472 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4473 APP_MENU_CALLBACK (on_message_settings),
4475 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4476 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4478 priv->show_toolbar_button = hildon_check_button_new (0);
4479 gtk_button_set_label (GTK_BUTTON (priv->show_toolbar_button), _("mcen_bd_show_toolbar"));
4480 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->show_toolbar_button),
4482 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->show_toolbar_button),
4483 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4484 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4485 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4486 gtk_button_set_alignment (GTK_BUTTON (priv->show_toolbar_button), 0.5, 0.5);
4487 gtk_button_set_alignment (GTK_BUTTON (priv->show_toolbar_button), 0.5, 0.5);
4492 emit_open_addressbook (GtkButton *button,
4493 ModestRecptEditor *editor)
4495 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4499 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4500 const gchar *label, GtkWidget *control)
4502 GtkWidget *abook_button;
4505 GtkWidget *label_widget;
4507 box = gtk_hbox_new (FALSE, 0);
4509 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4510 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4512 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4513 label_widget = gtk_label_new (label);
4514 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4515 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4517 gtk_container_add (GTK_CONTAINER (align), abook_button);
4518 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4519 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4520 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4521 if (title_size_group)
4522 gtk_size_group_add_widget (title_size_group, label_widget);
4523 if (value_size_group)
4524 gtk_size_group_add_widget (value_size_group, control);
4526 g_signal_connect (G_OBJECT (abook_button), "clicked",
4527 G_CALLBACK (emit_open_addressbook), control);
4533 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4535 ModestMsgEditWindowPrivate *priv = NULL;
4537 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4539 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4540 priv->max_chars_banner = NULL;
4544 has_pending_addresses (ModestRecptEditor *recpt_editor)
4546 const gchar *recipients = NULL;
4547 GSList *start_indexes = NULL, *end_indexes = NULL;
4548 GSList *current_start, *current_end;
4549 GtkTextBuffer *buffer;
4550 gint offset_delta = 0;
4552 gboolean has_recipients_to_add = FALSE;
4554 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4555 last_length = g_utf8_strlen (recipients, -1);
4556 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4561 current_start = start_indexes;
4562 current_end = end_indexes;
4563 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4565 while (current_start && !has_recipients_to_add) {
4567 gchar *start_ptr, *end_ptr;
4568 gint start_pos, end_pos;
4570 start_pos = (*((gint*) current_start->data)) + offset_delta;
4571 end_pos = (*((gint*) current_end->data)) + offset_delta;
4573 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4574 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4576 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4578 if (modest_text_utils_validate_recipient (address, NULL)) {
4579 if (!modest_address_book_has_address (address)) {
4580 has_recipients_to_add = TRUE;
4583 current_start = g_slist_next (current_start);
4584 current_end = g_slist_next (current_end);
4586 return has_recipients_to_add;
4590 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4592 ModestMsgEditWindowPrivate *priv = NULL;
4594 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4596 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4598 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4599 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4600 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))
4607 modest_msg_edit_window_set_custom_header_pairs (ModestMsgEditWindow *self,
4608 TnyList *header_pairs)
4610 ModestMsgEditWindowPrivate *priv = NULL;
4612 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
4613 g_return_if_fail (TNY_IS_LIST (header_pairs));
4615 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4616 g_object_unref (priv->custom_header_pairs);
4617 priv->custom_header_pairs = tny_list_copy (header_pairs);