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 <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <modest-wp-text-view.h>
65 #include <wptextbuffer.h>
66 #include <modest-scrollable.h>
67 #include <modest-isearch-toolbar.h>
68 #include "modest-msg-edit-window-ui-dimming.h"
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #include <libgnomevfs/gnome-vfs-mime.h>
72 #include <modest-utils.h>
73 #include <modest-ui-constants.h>
74 #include <modest-toolkit-utils.h>
76 #ifdef MODEST_USE_CALENDAR_WIDGETS
77 #include <calendar-ui-widgets.h>
79 #ifdef MODEST_TOOLKIT_HILDON2
80 #include <hildon/hildon.h>
81 #include "modest-maemo-utils.h"
82 #include "modest-hildon-includes.h"
83 #include "modest-color-button.h"
86 #define DEFAULT_MAIN_VBOX_SPACING 0
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #ifdef MODEST_TOOLKIT_HILDON2
90 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
91 #define DEFAULT_FONT_SCALE 1.5
92 #define DEFAULT_FONT_SIZE 3
93 #define DEFAULT_FONT 2
95 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
96 #define DEFAULT_FONT_SCALE 1.0
97 #define DEFAULT_FONT_SIZE 2
98 #define DEFAULT_FONT 2
100 #define ATTACHMENT_BUTTON_WIDTH 118
101 #define MAX_FROM_VALUE 36
102 #define MAX_BODY_LENGTH 128*1024
103 #define MAX_BODY_LINES 2048
105 static gboolean is_wp_text_buffer_started = FALSE;
107 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
108 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
109 static void modest_msg_edit_window_finalize (GObject *obj);
111 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
112 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
113 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
115 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
116 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
117 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
118 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
119 GtkTextIter *start, GtkTextIter *end,
121 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
122 static void body_insert_text (GtkTextBuffer *buffer,
123 GtkTextIter *location,
126 ModestMsgEditWindow *window);
127 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
128 static void subject_field_insert_text (GtkEditable *editable,
130 gint new_text_length,
132 ModestMsgEditWindow *window);
133 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
135 #ifdef MODEST_TOOLKIT_HILDON2
136 static void font_face_clicked (GtkToolButton *button,
137 ModestMsgEditWindow *window);
139 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
142 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
144 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
145 ModestRecptEditor *editor);
146 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
147 ModestMsgEditWindow *window);
149 /* ModestWindow methods implementation */
150 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
151 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
152 gboolean show_toolbar);
153 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
155 ModestMsgEditWindow *window);
156 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
157 static void subject_field_move_cursor (GtkEntry *entry,
158 GtkMovementStep step,
162 static void update_window_title (ModestMsgEditWindow *window);
165 static void modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
166 ModestMsgEditWindow *window);
167 static void modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
168 ModestMsgEditWindow *window);
169 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
171 GtkTextIter *match_start,
172 GtkTextIter *match_end);
174 static void remove_tags (WPTextBuffer *buffer);
176 static void on_account_removed (TnyAccountStore *account_store,
180 static void init_window (ModestMsgEditWindow *obj);
182 gboolean scroll_drag_timeout (gpointer userdata);
183 static void correct_scroll (ModestMsgEditWindow *w);
184 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
185 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
186 ModestMsgEditWindow *userdata);
187 static void text_buffer_mark_set (GtkTextBuffer *buffer,
190 ModestMsgEditWindow *userdata);
191 static void on_show_toolbar_button_toggled (GtkWidget *button,
192 ModestMsgEditWindow *window);
193 static void on_message_settings (GtkAction *action,
194 ModestMsgEditWindow *window);
195 static void setup_menu (ModestMsgEditWindow *self);
197 static void from_field_changed (GtkWidget *button,
198 ModestMsgEditWindow *self);
199 static void font_size_clicked (GtkToolButton *button,
200 ModestMsgEditWindow *window);
201 static void update_signature (ModestMsgEditWindow *self,
202 const gchar *old_account,
203 const gchar *new_account);
204 static void update_branding (ModestMsgEditWindow *self,
205 const gchar *new_account);
206 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
207 const gchar *label, GtkWidget *control);
208 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
209 static void DEBUG_BUFFER (WPTextBuffer *buffer)
213 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
215 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
216 while (!gtk_text_iter_is_end (&iter)) {
217 GString *output = g_string_new ("");
218 GSList *toggled_tags;
221 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
222 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
223 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
224 GtkTextTag *tag = (GtkTextTag *) node->data;
226 g_object_get (G_OBJECT (tag), "name", &name, NULL);
227 output = g_string_append (output, name);
228 g_string_append (output, " ");
230 output = g_string_append (output, "] OPENED [ ");
231 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
232 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
233 GtkTextTag *tag = (GtkTextTag *) node->data;
235 g_object_get (G_OBJECT (tag), "name", &name, NULL);
236 output = g_string_append (output, name);
237 g_string_append (output, " ");
239 output = g_string_append (output, "]\n");
240 g_debug ("%s", output->str);
241 g_string_free (output, TRUE);
242 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
244 g_debug ("END BUFFER");
248 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
249 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
253 /* static gboolean */
254 /* on_key_pressed (GtkWidget *self, */
255 /* GdkEventKey *event, */
256 /* gpointer user_data); */
258 /* list my signals */
265 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
266 struct _ModestMsgEditWindowPrivate {
268 GtkWidget *header_box;
270 ModestPairList *from_field_protos;
271 GtkWidget *from_field;
272 gchar *last_from_account;
273 gchar *original_account_name;
278 gchar *original_mailbox;
282 GtkWidget *bcc_field;
283 GtkWidget *subject_field;
284 GtkWidget *attachments_view;
285 GtkWidget *priority_icon;
286 GtkWidget *subject_box;
287 GtkWidget *send_button;
288 GtkWidget *bottom_send_button;
289 GtkWidget *bottom_send_button_container;
291 GtkWidget *cc_caption;
292 GtkWidget *bcc_caption;
293 gboolean update_caption_visibility;
294 GtkWidget *attachments_caption;
296 GtkTextBuffer *text_buffer;
298 GtkWidget *font_size_toolitem;
299 GtkWidget *font_face_toolitem;
300 GtkWidget *font_color_button;
301 GtkWidget *font_color_toolitem;
302 GSList *font_items_group;
303 GtkTreeModel *faces_model;
304 gint current_face_index;
305 GtkWidget *font_tool_button_label;
306 GtkTreeModel *sizes_model;
307 gint current_size_index;
308 GtkWidget *size_tool_button_label;
310 GtkWidget *isearch_toolbar;
313 GtkWidget *font_dialog;
315 GtkWidget *scrollable;
316 guint correct_scroll_idle;
317 guint scroll_drag_timeout_id;
321 TnyList *attachments;
326 TnyHeaderFlags priority_flags;
328 gboolean can_undo, can_redo;
329 gulong clipboard_change_handler_id;
330 gulong default_clipboard_change_handler_id;
331 gulong account_removed_handler_id;
332 guint clipboard_owner_idle;
333 gchar *clipboard_text;
342 GtkWidget *cc_button;
343 GtkWidget *bcc_button;
344 GtkWidget *show_toolbar_button;
346 GtkWidget *max_chars_banner;
348 GtkWidget *brand_icon;
349 GtkWidget *brand_label;
350 GtkWidget *brand_container;
352 TnyList *custom_header_pairs;
355 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
356 MODEST_TYPE_MSG_EDIT_WINDOW, \
357 ModestMsgEditWindowPrivate))
359 static GtkWindowClass *parent_class = NULL;
361 /* uncomment the following if you have defined any signals */
362 /* static guint signals[LAST_SIGNAL] = {0}; */
365 modest_msg_edit_window_get_type (void)
367 static GType my_type = 0;
369 static const GTypeInfo my_info = {
370 sizeof(ModestMsgEditWindowClass),
371 NULL, /* base init */
372 NULL, /* base finalize */
373 (GClassInitFunc) modest_msg_edit_window_class_init,
374 NULL, /* class finalize */
375 NULL, /* class data */
376 sizeof(ModestMsgEditWindow),
378 (GInstanceInitFunc) modest_msg_edit_window_init,
381 my_type = g_type_register_static (
382 #ifdef MODEST_TOOLKIT_HILDON2
383 MODEST_TYPE_HILDON2_WINDOW,
385 MODEST_TYPE_SHELL_WINDOW,
387 "ModestMsgEditWindow",
395 save_state (ModestWindow *self)
397 modest_widget_memory_save (modest_runtime_get_conf(),
398 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
403 restore_settings (ModestMsgEditWindow *self)
405 ModestConf *conf = NULL;
407 conf = modest_runtime_get_conf ();
409 /* Dim at start clipboard actions */
410 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
415 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
417 GObjectClass *gobject_class;
418 ModestWindowClass *modest_window_class;
419 gobject_class = (GObjectClass*) klass;
420 modest_window_class = (ModestWindowClass*) klass;
422 parent_class = g_type_class_peek_parent (klass);
423 gobject_class->finalize = modest_msg_edit_window_finalize;
425 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
426 modest_window_class->save_state_func = save_state;
427 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
429 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
433 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
435 ModestMsgEditWindowPrivate *priv;
436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
438 priv->msg_body = NULL;
439 priv->from_field = NULL;
440 priv->to_field = NULL;
441 priv->cc_field = NULL;
442 priv->bcc_field = NULL;
443 priv->subject_field = NULL;
444 priv->attachments = TNY_LIST (tny_simple_list_new ());
445 priv->images = TNY_LIST (tny_simple_list_new ());
446 priv->images_size = 0;
447 priv->images_count = 0;
450 priv->cc_caption = NULL;
451 priv->bcc_caption = NULL;
452 priv->update_caption_visibility = FALSE;
454 priv->priority_flags = 0;
456 priv->isearch_toolbar = NULL;
457 priv->last_search = NULL;
459 priv->draft_msg = NULL;
460 priv->outbox_msg = NULL;
461 priv->msg_uid = NULL;
463 priv->can_undo = FALSE;
464 priv->can_redo = FALSE;
465 priv->clipboard_change_handler_id = 0;
466 priv->default_clipboard_change_handler_id = 0;
467 priv->account_removed_handler_id = 0;
468 priv->clipboard_owner_idle = 0;
469 priv->clipboard_text = NULL;
472 priv->scroll_drag_timeout_id = 0;
473 priv->correct_scroll_idle = 0;
474 priv->last_upper = 0.0;
476 priv->font_dialog = NULL;
477 priv->app_menu = NULL;
479 priv->references = NULL;
480 priv->in_reply_to = NULL;
481 priv->max_chars_banner = NULL;
482 priv->custom_header_pairs = TNY_LIST (tny_simple_list_new ());
484 if (!is_wp_text_buffer_started) {
485 is_wp_text_buffer_started = TRUE;
486 wp_text_buffer_library_init ();
490 #ifdef MODEST_TOOLKIT_HILDON2
491 hildon_program_add_window (hildon_program_get_instance(),
497 multimailbox_get_default_mailbox (const gchar *account_name)
499 gchar *transport_account;
500 gchar *result = NULL;
502 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
504 TNY_ACCOUNT_TYPE_TRANSPORT);
505 if (transport_account) {
507 ModestProtocolRegistry *registry;
509 registry = modest_runtime_get_protocol_registry ();
511 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
512 MODEST_ACCOUNT_PROTO, TRUE);
514 ModestProtocol *protocol =
515 modest_protocol_registry_get_protocol_by_name (registry,
516 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
518 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
519 ModestPairList *pair_list;
521 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
524 ModestPair *pair = (ModestPair *) pair_list->data;
525 result = g_strdup ((const gchar *) pair->first);
526 modest_pair_list_free (pair_list);
537 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
539 static ModestPairList*
540 get_transports (void)
542 GSList *transports = NULL;
544 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
545 GSList *accounts = modest_account_mgr_account_names (account_mgr,
546 TRUE /* only enabled accounts. */);
548 GSList *cursor = accounts;
550 gchar *account_name = cursor->data;
553 gchar *transport_account;
554 gboolean multi_mailbox = FALSE;
555 ModestProtocol *protocol = NULL;
557 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
559 transport_account = modest_account_mgr_get_server_account_name
560 (modest_runtime_get_account_mgr (),
562 TNY_ACCOUNT_TYPE_TRANSPORT);
563 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
564 ModestPairList *pair_list;
565 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
568 transports = g_slist_concat (transports, pair_list);
569 multi_mailbox = TRUE;
574 if (!multi_mailbox) {
575 gchar *from_string = NULL;
577 from_string = modest_account_mgr_get_from_string (account_mgr,
579 if (from_string && account_name) {
580 gchar *name = account_name;
581 ModestPair *pair = modest_pair_new ((gpointer) name,
582 (gpointer) from_string , TRUE);
583 transports = g_slist_prepend (transports, pair);
588 cursor = cursor->next;
590 g_slist_free (accounts); /* only free the accounts, not the elements,
591 * because they are used in the pairlist */
595 static void window_focus (GtkWindow *window,
599 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
603 scroll_drag_timeout (gpointer userdata)
605 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
606 ModestMsgEditWindowPrivate *priv;
608 /* It could happen that the window was already closed */
609 if (!GTK_WIDGET_VISIBLE (win))
612 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
614 correct_scroll_without_drag_check (win, TRUE);
616 priv->scroll_drag_timeout_id = 0;
622 correct_scroll_without_drag_check_idle (gpointer userdata)
624 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
625 ModestMsgEditWindowPrivate *priv;
627 GdkRectangle rectangle;
628 gint offset_min, offset_max;
632 /* It could happen that the window was already closed */
633 if (!GTK_WIDGET_VISIBLE (w))
636 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
638 insert = gtk_text_buffer_get_insert (priv->text_buffer);
639 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
641 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
642 offset_min = priv->msg_body->allocation.y + rectangle.y;
643 offset_max = offset_min + rectangle.height;
645 vadj = modest_scrollable_get_vadjustment (MODEST_SCROLLABLE (priv->scrollable));
646 offset_min = MAX (offset_min - 48, 0);
647 offset_max = MIN (offset_max + 48, vadj->upper);
649 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
651 priv->correct_scroll_idle = 0;
656 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
658 ModestMsgEditWindowPrivate *priv;
660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
662 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
665 if (priv->correct_scroll_idle > 0) {
669 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
670 (GSourceFunc) correct_scroll_without_drag_check_idle,
676 correct_scroll (ModestMsgEditWindow *w)
678 ModestMsgEditWindowPrivate *priv;
680 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
681 if (gtk_grab_get_current () == priv->msg_body) {
682 if (priv->scroll_drag_timeout_id == 0) {
683 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
685 (GSourceFunc) scroll_drag_timeout,
692 correct_scroll_without_drag_check (w, TRUE);
696 text_buffer_end_user_action (GtkTextBuffer *buffer,
697 ModestMsgEditWindow *userdata)
700 correct_scroll (userdata);
704 text_buffer_mark_set (GtkTextBuffer *buffer,
707 ModestMsgEditWindow *userdata)
709 gtk_text_buffer_begin_user_action (buffer);
710 gtk_text_buffer_end_user_action (buffer);
714 cut_clipboard_check (GtkTextView *text_view,
717 GtkTextBuffer *buffer;
719 buffer = gtk_text_view_get_buffer (text_view);
720 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
721 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
726 copy_clipboard_check (GtkTextView *text_view,
729 GtkTextBuffer *buffer;
731 buffer = gtk_text_view_get_buffer (text_view);
732 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
733 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
738 attachment_deleted (ModestAttachmentsView *attachments_view,
741 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
746 body_size_request (GtkWidget *body,
750 ModestMsgEditWindowPrivate *priv;
753 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(user_data);
755 /* Make sure the body always get at least 70 pixels */
756 if (req->height < 70)
759 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
760 if (priv->header_box->allocation.height + req->height > GTK_WIDGET (user_data)->allocation.height) {
761 if (!GTK_WIDGET_VISIBLE (priv->bottom_send_button_container)) {
762 gtk_widget_show (priv->bottom_send_button_container);
765 if (GTK_WIDGET_VISIBLE (priv->bottom_send_button_container)) {
766 gtk_widget_hide (priv->bottom_send_button_container);
772 connect_signals (ModestMsgEditWindow *obj)
774 ModestMsgEditWindowPrivate *priv;
776 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
778 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
779 G_CALLBACK (text_buffer_refresh_attributes), obj);
780 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
781 G_CALLBACK (text_buffer_can_undo), obj);
782 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
783 G_CALLBACK (text_buffer_can_redo), obj);
784 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
785 G_CALLBACK (body_changed), obj);
786 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
787 G_CALLBACK (body_insert_text), obj);
788 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
789 G_CALLBACK (body_changed), obj);
790 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
791 G_CALLBACK (text_buffer_end_user_action), obj);
792 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
793 G_CALLBACK (text_buffer_mark_set), obj);
794 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
795 G_CALLBACK (text_buffer_apply_tag), obj);
796 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
797 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
798 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
799 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
800 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
801 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
803 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
804 G_CALLBACK (modest_ui_actions_on_send), obj);
806 g_signal_connect (G_OBJECT (priv->bottom_send_button), "clicked",
807 G_CALLBACK (modest_ui_actions_on_send), obj);
809 if (GTK_IS_COMBO_BOX (priv->from_field)) {
810 g_signal_connect (G_OBJECT (priv->from_field), "changed",
811 G_CALLBACK (from_field_changed), obj);
813 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
814 G_CALLBACK (from_field_changed), obj);
817 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
818 G_CALLBACK (msg_body_focus), obj);
819 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
820 G_CALLBACK (msg_body_focus), obj);
821 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
822 G_CALLBACK (body_size_request), obj);
823 if (GTK_IS_WINDOW (obj)) {
824 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
826 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
827 "changed", G_CALLBACK (recpt_field_changed), obj);
828 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
829 "changed", G_CALLBACK (recpt_field_changed), obj);
830 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
831 "changed", G_CALLBACK (recpt_field_changed), obj);
832 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
833 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
834 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
836 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-search",
837 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_search), obj);
838 g_signal_connect (G_OBJECT (priv->isearch_toolbar), "isearch-close",
839 G_CALLBACK (modest_msg_edit_window_isearch_toolbar_close), obj);
841 priv->clipboard_change_handler_id =
842 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
843 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
844 priv->default_clipboard_change_handler_id =
845 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
846 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
848 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
849 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
850 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
854 init_wp_text_view_style ()
856 static gboolean initialized = FALSE;
859 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
865 init_window (ModestMsgEditWindow *obj)
867 GtkWidget *to_caption, *subject_caption;
868 GtkWidget *main_vbox;
869 ModestMsgEditWindowPrivate *priv;
870 GtkActionGroup *action_group;
871 ModestWindowPrivate *parent_priv;
872 GError *error = NULL;
874 GtkSizeGroup *title_size_group;
875 GtkSizeGroup *value_size_group;
876 GtkWidget *window_box;
877 GtkWidget *window_align;
878 #if (GTK_MINOR_VERSION >= 10)
879 GdkAtom deserialize_type;
881 GtkWidget *from_send_hbox;
882 GtkWidget *send_icon;
883 GtkWidget *attachments_label;
884 GtkWidget *branding_box;
885 GtkWidget *from_caption;
887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
888 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
890 parent_priv->ui_manager = gtk_ui_manager_new();
891 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
892 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
894 /* Add common actions */
895 gtk_action_group_add_actions (action_group,
896 modest_msg_edit_action_entries,
897 G_N_ELEMENTS (modest_msg_edit_action_entries),
899 gtk_action_group_add_actions (action_group,
900 hildon2_msg_edit_action_entries,
901 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
903 gtk_action_group_add_toggle_actions (action_group,
904 modest_msg_edit_toggle_action_entries,
905 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
907 gtk_action_group_add_radio_actions (action_group,
908 modest_msg_edit_alignment_radio_action_entries,
909 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
911 G_CALLBACK (modest_ui_actions_on_change_justify),
913 gtk_action_group_add_radio_actions (action_group,
914 modest_msg_edit_priority_action_entries,
915 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
917 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
919 gtk_action_group_add_radio_actions (action_group,
920 modest_msg_edit_file_format_action_entries,
921 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
922 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
923 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
925 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
926 g_object_unref (action_group);
928 /* Load the UI definition */
929 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
932 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
933 g_clear_error (&error);
936 parent_priv->menubar = NULL;
938 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
939 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
941 /* Note: This ModestPairList* must exist for as long as the picker
942 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
943 * so it can't know how to manage its memory. */
944 priv->from_field = modest_toolkit_factory_create_selector (modest_runtime_get_toolkit_factory (),
946 modest_selector_set_value_max_chars (priv->from_field, MAX_FROM_VALUE);
947 if (GTK_IS_COMBO_BOX (priv->from_field)) {
948 from_caption = modest_toolkit_utils_create_captioned (title_size_group, NULL,
949 _("mail_va_from"), FALSE,
951 gtk_widget_show (from_caption);
953 #ifdef MODEST_TOOLKIT_HILDON2
954 modest_toolkit_utils_set_hbutton_layout (title_size_group, NULL,
955 _("mail_va_from"), priv->from_field);
956 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
957 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
958 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
959 from_caption = priv->from_field;
963 priv->to_field = modest_recpt_editor_new ();
964 priv->cc_field = modest_recpt_editor_new ();
965 priv->bcc_field = modest_recpt_editor_new ();
966 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
967 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
968 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
969 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
970 priv->priority_icon = gtk_image_new ();
971 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
972 priv->subject_field = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
973 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
974 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
975 modest_entry_set_hint (priv->subject_field, _("mail_va_no_subject"));
977 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
978 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
980 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
981 priv->attachments_view = modest_attachments_view_new (NULL);
982 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
983 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
985 priv->header_box = gtk_vbox_new (FALSE, 0);
987 to_caption = _create_addressbook_box
988 (title_size_group, value_size_group,
989 _("mail_va_to"), priv->to_field);
990 priv->cc_caption = _create_addressbook_box
991 (title_size_group, value_size_group,
992 _("mail_va_cc"), priv->cc_field);
993 priv->bcc_caption = _create_addressbook_box
994 (title_size_group, value_size_group,
995 _("mail_va_hotfix1"), priv->bcc_field);
996 subject_caption = modest_toolkit_utils_create_captioned (title_size_group, value_size_group,
997 _("mail_va_subject"), FALSE, priv->subject_box);
998 priv->attachments_caption = modest_toolkit_utils_create_captioned_with_size_type (NULL, NULL,
999 _("mail_va_attachment"),
1001 priv->attachments_view,
1002 #ifdef MODEST_TOOLKIT_HILDON2
1003 HILDON_SIZE_AUTO_WIDTH |
1004 HILDON_SIZE_AUTO_HEIGHT
1009 attachments_label = modest_toolkit_utils_captioned_get_label_widget (priv->attachments_caption);
1010 #ifdef MAEMO_CHANGES
1011 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
1015 #ifdef MODEST_TOOLKIT_HILDON2
1016 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
1017 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
1019 priv->send_button = gtk_button_new ();
1020 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, GTK_ICON_SIZE_BUTTON);
1022 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
1023 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
1025 priv->bottom_send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
1026 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
1027 gtk_container_add (GTK_CONTAINER (priv->bottom_send_button), send_icon);
1028 gtk_widget_set_size_request (GTK_WIDGET (priv->bottom_send_button), 148, -1);
1030 priv->bottom_send_button_container = gtk_hbox_new (FALSE, 0);
1031 gtk_widget_show (priv->bottom_send_button_container);
1032 gtk_box_pack_end (GTK_BOX (priv->bottom_send_button_container), priv->bottom_send_button, FALSE, FALSE, 0);
1033 gtk_widget_show (priv->bottom_send_button_container);
1035 g_object_unref (title_size_group);
1036 g_object_unref (value_size_group);
1038 priv->brand_icon = gtk_image_new ();
1039 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
1040 priv->brand_label = gtk_label_new (NULL);
1041 #ifdef MODEST_TOOLKIT_HILDON2
1042 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
1044 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
1045 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
1046 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
1048 from_send_hbox = gtk_hbox_new (FALSE, 0);
1049 gtk_box_pack_start (GTK_BOX (from_send_hbox), from_caption, TRUE, TRUE, 0);
1050 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
1052 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
1053 gtk_widget_show (branding_box);
1054 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
1055 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
1057 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
1058 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
1059 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
1060 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
1063 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
1064 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
1065 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
1066 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
1067 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
1068 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
1069 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
1070 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
1072 init_wp_text_view_style ();
1074 priv->msg_body = modest_wp_text_view_new ();
1077 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
1078 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1079 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
1080 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1081 #if (GTK_MINOR_VERSION >= 10)
1082 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
1083 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1085 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1086 deserialize_type, TRUE);
1088 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1090 priv->isearch_toolbar = modest_toolkit_factory_create_isearch_toolbar (modest_runtime_get_toolkit_factory (),
1092 gtk_widget_set_no_show_all (priv->isearch_toolbar, TRUE);
1094 priv->scrollable = modest_toolkit_factory_create_scrollable (modest_runtime_get_toolkit_factory ());
1096 g_object_set (G_OBJECT (priv->scrollable), "horizontal-policy", GTK_POLICY_NEVER, NULL);
1098 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1099 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1100 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), MODEST_MARGIN_HALF, 0,
1101 MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1103 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1104 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1105 gtk_box_pack_start (GTK_BOX (main_vbox), priv->bottom_send_button_container, FALSE, FALSE, 0);
1106 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1108 modest_scrollable_add_with_viewport (MODEST_SCROLLABLE (priv->scrollable), window_align);
1109 gtk_widget_show_all (GTK_WIDGET(priv->scrollable));
1111 window_box = gtk_vbox_new (FALSE, 0);
1112 gtk_container_add (GTK_CONTAINER(obj), window_box);
1114 gtk_box_pack_start (GTK_BOX (window_box), priv->scrollable, TRUE, TRUE, 0);
1119 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1121 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1123 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1124 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1125 priv->clipboard_change_handler_id))
1126 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1127 priv->clipboard_change_handler_id);
1128 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1129 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1130 priv->default_clipboard_change_handler_id))
1131 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1132 priv->default_clipboard_change_handler_id);
1134 if (priv->account_removed_handler_id &&
1135 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1136 priv->account_removed_handler_id))
1137 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1138 priv->account_removed_handler_id);
1142 modest_msg_edit_window_finalize (GObject *obj)
1144 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1146 g_object_unref (priv->custom_header_pairs);
1148 if (priv->max_chars_banner) {
1149 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1150 priv->max_chars_banner = FALSE;
1153 /* Sanity check: shouldn't be needed, the window mgr should
1154 call this function before */
1155 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1157 if (priv->font_dialog != NULL) {
1158 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1161 if (priv->clipboard_text != NULL) {
1162 g_free (priv->clipboard_text);
1163 priv->clipboard_text = NULL;
1166 if (priv->draft_msg != NULL) {
1167 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1168 if (TNY_IS_HEADER (header)) {
1169 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1170 modest_window_mgr_unregister_header (mgr, header);
1172 g_object_unref (priv->draft_msg);
1173 priv->draft_msg = NULL;
1175 if (priv->outbox_msg != NULL) {
1176 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1177 if (TNY_IS_HEADER (header)) {
1178 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1179 modest_window_mgr_unregister_header (mgr, header);
1181 g_object_unref (priv->outbox_msg);
1182 priv->outbox_msg = NULL;
1184 if (priv->correct_scroll_idle > 0) {
1185 g_source_remove (priv->correct_scroll_idle);
1186 priv->correct_scroll_idle = 0;
1188 if (priv->scroll_drag_timeout_id > 0) {
1189 g_source_remove (priv->scroll_drag_timeout_id);
1190 priv->scroll_drag_timeout_id = 0;
1192 if (priv->clipboard_owner_idle > 0) {
1193 g_source_remove (priv->clipboard_owner_idle);
1194 priv->clipboard_owner_idle = 0;
1196 if (priv->original_account_name)
1197 g_free (priv->original_account_name);
1198 if (priv->original_mailbox)
1199 g_free (priv->original_mailbox);
1200 g_free (priv->msg_uid);
1201 g_free (priv->last_search);
1202 g_slist_free (priv->font_items_group);
1203 g_free (priv->references);
1204 g_free (priv->in_reply_to);
1205 g_object_unref (priv->attachments);
1206 g_object_unref (priv->images);
1208 /* This had to stay alive for as long as the picker that used it: */
1209 modest_pair_list_free (priv->from_field_protos);
1211 G_OBJECT_CLASS(parent_class)->finalize (obj);
1215 pixbuf_size_prepared (GdkPixbufLoader *loader,
1218 ModestMsgEditWindow *self)
1220 gint new_height, new_width;
1223 new_height = height;
1227 if (width > IMAGE_MAX_WIDTH) {
1228 new_height = height * IMAGE_MAX_WIDTH / width;
1229 new_width = IMAGE_MAX_WIDTH;
1232 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1236 pixbuf_from_stream (TnyStream *stream,
1237 const gchar *mime_type,
1238 guint64 *stream_size,
1239 ModestMsgEditWindow *self)
1241 GdkPixbufLoader *loader;
1244 GError *error = NULL;
1248 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1250 if (loader == NULL) {
1255 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1257 modest_window_show_progress (MODEST_WINDOW (self), TRUE);
1259 tny_stream_reset (TNY_STREAM (stream));
1260 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1261 unsigned char read_buffer[128];
1263 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1265 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1268 /* Allow some UI responsiveness */
1269 while (gtk_events_pending ())
1270 gtk_main_iteration ();
1272 modest_window_show_progress (MODEST_WINDOW (self), FALSE);
1274 gdk_pixbuf_loader_close (loader, &error);
1277 g_error_free (error);
1278 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1280 g_object_ref (pixbuf);
1281 g_object_unref (loader);
1286 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1287 GdkPixbuf *new_pixbuf;
1289 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1290 gdk_pixbuf_get_width (pixbuf);
1291 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1292 g_object_unref (pixbuf);
1293 pixbuf = new_pixbuf;
1297 *stream_size = size;
1303 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1305 ModestMsgEditWindowPrivate *priv;
1308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1310 g_object_ref (self);
1311 for (iter = tny_list_create_iterator (attachments);
1312 !tny_iterator_is_done (iter);
1313 tny_iterator_next (iter)) {
1314 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1315 const gchar *cid = tny_mime_part_get_content_id (part);
1316 const gchar *mime_type = tny_mime_part_get_content_type (part);
1317 if ((cid != NULL)&&(mime_type != NULL)) {
1318 guint64 stream_size;
1319 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1320 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1323 g_object_unref (stream);
1325 if (pixbuf != NULL) {
1326 priv->images_count ++;
1327 priv->images_size += stream_size;
1328 #ifndef MODEST_HAVE_LIBWPEDITOR_PLUS
1329 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1331 g_object_unref (pixbuf);
1334 g_object_unref (part);
1336 g_object_unref (iter);
1337 g_object_unref (self);
1341 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1343 TnyMimePart *parent = NULL;
1344 const gchar *content_type = NULL;
1345 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1347 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1349 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1350 parent = g_object_ref (msg);
1351 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1352 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1355 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1356 iter = tny_list_create_iterator (parts);
1357 while (!tny_iterator_is_done (iter)) {
1359 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1360 content_type = tny_mime_part_get_content_type (part);
1361 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1365 g_object_unref (part);
1367 tny_iterator_next (iter);
1369 g_object_unref (iter);
1370 g_object_unref (parts);
1373 if (parent != NULL) {
1374 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1377 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1378 iter = tny_list_create_iterator (parts);
1379 while (!tny_iterator_is_done (iter)) {
1381 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1382 content_type = tny_mime_part_get_content_type (part);
1383 if (content_type && g_str_has_prefix (content_type, "image/")) {
1384 tny_list_prepend (priv->images, (GObject *) part);
1386 g_object_unref (part);
1387 tny_iterator_next (iter);
1389 g_object_unref (iter);
1390 g_object_unref (parts);
1391 g_object_unref (parent);
1396 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1399 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1401 for (iter = tny_list_create_iterator (attachments) ;
1402 !tny_iterator_is_done (iter);
1403 tny_iterator_next (iter)) {
1404 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1405 const gchar *cid = tny_mime_part_get_content_id (part);
1407 char *invalid = NULL;
1408 gint int_cid = strtol (cid, &invalid, 10);
1409 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1410 priv->next_cid = int_cid + 1;
1413 g_object_unref (part);
1415 g_object_unref (iter);
1419 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1422 gchar *to, *cc, *bcc, *subject;
1424 ModestMsgEditWindowPrivate *priv;
1425 ModestWindowPrivate *parent_priv;
1427 TnyHeaderFlags priority_flags;
1428 TnyFolder *msg_folder;
1429 gboolean is_html = FALSE;
1430 gboolean field_view_set;
1431 TnyList *orig_header_pairs;
1433 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1434 g_return_if_fail (TNY_IS_MSG (msg));
1436 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1437 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1439 header = tny_msg_get_header (msg);
1440 to = tny_header_dup_to (header);
1441 cc = tny_header_dup_cc (header);
1442 bcc = tny_header_dup_bcc (header);
1443 subject = tny_header_dup_subject (header);
1445 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1446 priority_flags = tny_header_get_priority (header);
1449 gchar *quoted_names = modest_text_utils_quote_names (to);
1450 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1451 g_free (quoted_names);
1454 field_view_set = TRUE;
1456 gchar *quoted_names = modest_text_utils_quote_names (cc);
1457 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1458 g_free (quoted_names);
1459 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1460 gtk_widget_show (priv->cc_caption);
1461 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1462 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1463 gtk_widget_hide (priv->cc_caption);
1464 field_view_set = FALSE;
1466 modest_togglable_set_active (priv->cc_button, field_view_set);
1468 field_view_set = TRUE;
1470 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1471 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1472 g_free (quoted_names);
1473 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1474 gtk_widget_show (priv->bcc_caption);
1475 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1476 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1477 gtk_widget_hide (priv->bcc_caption);
1478 field_view_set = FALSE;
1480 modest_togglable_set_active (priv->bcc_button, field_view_set);
1484 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1485 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1488 update_window_title (self);
1490 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1491 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1493 if ((body == NULL)||(body[0] == '\0')) {
1495 body = modest_text_utils_convert_to_html ("");
1498 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1499 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1502 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1505 /* Add attachments to the view */
1506 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1507 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1508 if (tny_list_get_length (priv->attachments) == 0) {
1509 gtk_widget_hide (priv->attachments_caption);
1511 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1512 gtk_widget_show_all (priv->attachments_caption);
1514 get_related_images (self, msg);
1515 update_next_cid (self, priv->attachments);
1516 update_next_cid (self, priv->images);
1517 replace_with_images (self, priv->images);
1519 if (preserve_is_rich && !is_html) {
1520 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1521 /* Get the default format required from configuration */
1522 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1523 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1526 /* Set the default focus depending on having already a To: field or not */
1527 if ((!to)||(*to == '\0')) {
1528 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1530 gtk_widget_grab_focus (priv->msg_body);
1533 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1535 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1536 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1538 modest_msg_edit_window_set_modified (self, FALSE);
1540 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1541 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1542 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1543 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1545 if (priv->msg_uid) {
1546 g_free (priv->msg_uid);
1547 priv->msg_uid = NULL;
1550 /* we should set a reference to the incoming message if it is a draft */
1551 msg_folder = tny_msg_get_folder (msg);
1553 if (modest_tny_folder_is_local_folder (msg_folder)) {
1554 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1555 if (type == TNY_FOLDER_TYPE_INVALID)
1556 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1558 if (type == TNY_FOLDER_TYPE_DRAFTS)
1559 priv->draft_msg = g_object_ref(msg);
1560 if (type == TNY_FOLDER_TYPE_OUTBOX)
1561 priv->outbox_msg = g_object_ref(msg);
1562 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1564 g_object_unref (msg_folder);
1567 orig_header_pairs = TNY_LIST (tny_simple_list_new ());
1568 tny_mime_part_get_header_pairs (TNY_MIME_PART (msg), orig_header_pairs);
1569 modest_msg_edit_window_set_custom_header_pairs (self, orig_header_pairs);
1570 g_object_unref (orig_header_pairs);
1578 #ifndef MODEST_TOOLKIT_HILDON2
1580 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1583 GList *item_children, *node;
1584 GtkWidget *bin_child;
1586 bin_child = gtk_bin_get_child (GTK_BIN(item));
1588 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1590 for (node = item_children; node != NULL; node = g_list_next (node)) {
1591 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1592 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1595 g_list_free (item_children);
1599 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1602 GList *item_children, *node;
1604 box = gtk_bin_get_child (GTK_BIN (item));
1605 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1606 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1608 for (node = item_children; node != NULL; node = g_list_next (node)) {
1609 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1610 if (GTK_IS_TOGGLE_BUTTON (node->data))
1611 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1612 else if (GTK_IS_BUTTON (node->data))
1613 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1615 g_list_free (item_children);
1620 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1622 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1623 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1624 GtkWidget *placeholder;
1625 GtkWidget *tool_item;
1630 GtkWidget *sizes_menu;
1634 #ifndef MODEST_TOOLKIT_HILDON2
1635 GSList *radio_group, *node;
1636 GtkWidget *fonts_menu;
1640 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1641 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1642 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar),
1643 #ifdef MODEST_TOOLKIT_HILDON2
1644 HILDON_ICON_SIZE_FINGER
1646 GTK_ICON_SIZE_LARGE_TOOLBAR
1649 modest_window_add_toolbar (MODEST_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1651 /* Font color placeholder */
1652 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1653 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1656 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1657 #ifdef MODEST_TOOLKIT_HILDON2
1658 priv->font_color_button = modest_color_button_new ();
1660 priv->font_color_button = gtk_color_button_new ();
1662 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1663 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1664 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1665 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1666 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1667 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1668 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1669 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1671 G_CALLBACK (modest_msg_edit_window_color_button_change),
1674 /* Font size and face placeholder */
1675 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1676 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1678 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1679 priv->size_tool_button_label = gtk_label_new (NULL);
1680 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1681 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1682 size_text, "</span>", NULL);
1683 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1684 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1686 #ifdef MODEST_TOOLKIT_HILDON2
1687 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1689 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1690 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1691 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1692 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1693 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1694 gtk_widget_set_sensitive (arrow, FALSE);
1695 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1696 sizes_menu = gtk_menu_new ();
1697 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1698 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1701 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1702 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1704 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1708 if (wp_font_size[size_index] == 12)
1709 priv->current_size_index = size_index;
1713 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1714 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1715 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1716 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1717 priv->font_size_toolitem = tool_item;
1719 #ifdef MODEST_TOOLKIT_HILDON2
1721 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, ""));
1722 priv->font_tool_button_label = gtk_label_new (NULL);
1723 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1724 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1725 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1727 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1728 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1729 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1730 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1731 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1732 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1733 gtk_widget_set_sensitive (arrow, FALSE);
1734 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1736 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1737 priv->font_tool_button_label = gtk_label_new (NULL);
1738 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1739 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1741 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1742 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1743 gtk_widget_show (priv->font_tool_button_label);
1744 gtk_widget_show (GTK_WIDGET (tool_item));
1745 fonts_menu = gtk_menu_new ();
1748 #ifdef MODEST_TOOLKIT_HILDON2
1749 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1750 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1753 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1755 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1756 0, wp_get_font_name (font_index),
1759 if (font_index == DEFAULT_FONT)
1760 priv->current_face_index = font_index;
1762 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1763 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1764 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1765 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1766 priv->font_face_toolitem = tool_item;
1768 priv->font_items_group = NULL;
1770 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1771 GtkWidget *font_menu_item;
1772 GtkWidget *child_label;
1774 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1775 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1776 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1777 wp_get_font_name (font_index), "</span>", NULL);
1778 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1781 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1782 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1783 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1784 gtk_widget_show (font_menu_item);
1786 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1789 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1790 GtkWidget *item = (GtkWidget *) node->data;
1791 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1794 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1795 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1796 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1797 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1798 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1799 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1800 priv->font_face_toolitem = tool_item;
1803 /* Set expand and homogeneous for remaining items */
1804 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1805 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1806 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1807 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1808 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1809 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1810 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsInsertImage");
1811 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1812 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1814 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1815 will not show the tool items added to the placeholders) */
1816 gtk_widget_show_all (parent_priv->toolbar);
1818 /* Set the no show all *after* showing all items. We do not
1819 want the toolbar to be shown with a show all because it
1820 could go against the gconf setting regarding showing or not
1821 the toolbar of the editor window */
1822 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1828 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1831 ModestWindowPrivate *parent_priv;
1832 ModestMsgEditWindowPrivate *priv;
1833 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1834 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1835 ModestWindowMgr *mgr = NULL;
1837 g_return_val_if_fail (msg, NULL);
1838 g_return_val_if_fail (account_name, NULL);
1840 mgr = modest_runtime_get_window_mgr ();
1842 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1844 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1845 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1847 /* Menubar. Update the state of some toggles */
1848 priv->from_field_protos = get_transports ();
1849 priv->original_mailbox = NULL;
1850 modest_selector_set_pair_list (priv->from_field, priv->from_field_protos);
1851 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1852 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1853 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1854 modest_selector_set_active_id (priv->from_field, (gpointer) mailbox);
1855 priv->original_mailbox = g_strdup (mailbox);
1856 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1857 /* We set the first mailbox as the active mailbox */
1858 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1859 if (priv->original_mailbox != NULL)
1860 modest_selector_set_active_id (priv->from_field,
1861 (gpointer) priv->original_mailbox);
1863 modest_selector_set_active_id (priv->from_field,
1864 (gpointer) account_name);
1866 modest_selector_set_active_id (priv->from_field, (gpointer) account_name);
1868 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
1869 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1870 if (!GTK_IS_COMBO_BOX (priv->from_field)) {
1871 #ifdef HILDON_TOOLKIT_HILDON2
1872 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1874 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1875 hildon_touch_selector_get_current_text
1876 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1879 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1880 modest_window_add_toolbar (MODEST_WINDOW (obj), GTK_TOOLBAR (priv->isearch_toolbar));
1883 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1885 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1887 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1888 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1890 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1892 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1893 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1894 /* Add common dimming rules */
1895 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1896 modest_msg_edit_window_toolbar_dimming_entries,
1897 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1898 MODEST_WINDOW (obj));
1899 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1900 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1901 MODEST_WINDOW (obj));
1902 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1903 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1904 MODEST_WINDOW (obj));
1905 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1906 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1907 MODEST_WINDOW (obj));
1908 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1909 G_CALLBACK (modest_ui_dimming_rules_on_send),
1910 MODEST_WINDOW (obj));
1911 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->bottom_send_button,
1912 G_CALLBACK (modest_ui_dimming_rules_on_send),
1913 MODEST_WINDOW (obj));
1914 /* Insert dimming rules group for this window */
1915 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1916 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1918 /* Setup app menu */
1919 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1921 /* Checks the dimming rules */
1922 g_object_unref (toolbar_rules_group);
1923 g_object_unref (clipboard_rules_group);
1924 gtk_widget_hide (priv->priority_icon);
1925 gtk_widget_queue_resize (priv->subject_box);
1926 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1928 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1930 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1931 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1932 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1933 priv->update_caption_visibility = TRUE;
1935 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1937 /* Track account-removed signal, this window should be closed
1938 in the case we're creating a mail associated to the account
1940 priv->account_removed_handler_id =
1941 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1943 G_CALLBACK(on_account_removed),
1946 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1948 return (ModestWindow*) obj;
1952 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1954 GString **string_buffer = (GString **) user_data;
1956 *string_buffer = g_string_append (*string_buffer, buffer);
1962 * @result: A new string which should be freed with g_free().
1965 get_formatted_data (ModestMsgEditWindow *edit_window)
1967 ModestMsgEditWindowPrivate *priv;
1968 GString *string_buffer = g_string_new ("");
1970 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1972 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1974 modest_text_utils_hyperlinkify (string_buffer);
1976 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1978 return g_string_free (string_buffer, FALSE);
1983 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1986 const gchar *account_name;
1987 ModestMsgEditWindowPrivate *priv;
1988 TnyIterator *att_iter;
1989 const gchar *picker_active_id;
1991 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1995 picker_active_id = modest_selector_get_active_id (priv->from_field);
1996 g_return_val_if_fail (picker_active_id, NULL);
1997 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1999 /* don't free these (except from) */
2000 data = g_slice_new0 (MsgData);
2001 data->from = g_strdup ((gchar *) modest_selector_get_active_display_name (priv->from_field));
2002 data->account_name = g_strdup (account_name);
2003 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
2004 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
2005 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
2006 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
2007 data->references = g_strdup (priv->references);
2008 data->in_reply_to = g_strdup (priv->in_reply_to);
2009 if (priv->draft_msg) {
2010 data->draft_msg = g_object_ref (priv->draft_msg);
2011 } else if (priv->outbox_msg) {
2012 data->draft_msg = g_object_ref (priv->outbox_msg);
2014 data->draft_msg = NULL;
2017 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2019 gtk_text_buffer_get_bounds (buf, &b, &e);
2020 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
2022 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
2023 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
2025 data->html_body = NULL;
2027 /* deep-copy the data */
2028 att_iter = tny_list_create_iterator (priv->attachments);
2029 data->attachments = NULL;
2030 while (!tny_iterator_is_done (att_iter)) {
2031 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2032 if (!(TNY_IS_MIME_PART(part))) {
2033 g_warning ("strange data in attachment list");
2034 g_object_unref (part);
2035 tny_iterator_next (att_iter);
2038 data->attachments = g_list_append (data->attachments,
2040 tny_iterator_next (att_iter);
2042 g_object_unref (att_iter);
2044 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
2045 att_iter = tny_list_create_iterator (priv->images);
2046 data->images = NULL;
2047 while (!tny_iterator_is_done (att_iter)) {
2048 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
2050 if (!(TNY_IS_MIME_PART(part))) {
2051 g_warning ("strange data in attachment list");
2052 g_object_unref (part);
2053 tny_iterator_next (att_iter);
2056 cid = tny_mime_part_get_content_id (part);
2058 gchar *image_tag_id;
2059 GtkTextTag *image_tag;
2061 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
2062 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
2063 g_free (image_tag_id);
2065 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
2067 ((gtk_text_iter_has_tag (&iter, image_tag))||
2068 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
2069 data->images = g_list_append (data->images,
2070 g_object_ref (part));
2072 g_object_unref (part);
2073 tny_iterator_next (att_iter);
2075 g_object_unref (att_iter);
2077 data->priority_flags = priv->priority_flags;
2078 data->custom_header_pairs = tny_list_copy (priv->custom_header_pairs);
2085 unref_gobject (GObject *obj, gpointer data)
2087 if (!G_IS_OBJECT(obj))
2089 g_object_unref (obj);
2093 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
2096 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
2104 g_free (data->from);
2105 g_free (data->subject);
2106 g_free (data->plain_body);
2107 g_free (data->html_body);
2108 g_free (data->account_name);
2109 g_free (data->references);
2110 g_free (data->in_reply_to);
2112 g_object_unref (data->custom_header_pairs);
2114 if (data->draft_msg != NULL) {
2115 g_object_unref (data->draft_msg);
2116 data->draft_msg = NULL;
2119 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
2120 g_list_free (data->attachments);
2121 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
2122 g_list_free (data->images);
2124 g_slice_free (MsgData, data);
2128 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
2130 guint64 *parts_size)
2132 ModestMsgEditWindowPrivate *priv;
2134 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2136 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
2138 /* TODO: add images */
2139 *parts_size += priv->images_size;
2140 *parts_count += priv->images_count;
2145 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
2148 ModestMsgEditWindowPrivate *priv = NULL;
2149 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
2151 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2153 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2155 return MODEST_MSG_EDIT_FORMAT_HTML;
2157 return MODEST_MSG_EDIT_FORMAT_TEXT;
2161 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
2162 ModestMsgEditFormat format)
2164 ModestMsgEditWindowPrivate *priv;
2165 ModestWindowPrivate *parent_priv;
2167 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2169 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
2172 case MODEST_MSG_EDIT_FORMAT_HTML:
2173 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2174 update_signature (self, priv->last_from_account, priv->last_from_account);
2175 if (parent_priv->toolbar)
2176 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2177 MODEST_MSG_EDIT_WINDOW (self));
2179 case MODEST_MSG_EDIT_FORMAT_TEXT:
2180 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2181 if (parent_priv->toolbar)
2182 on_show_toolbar_button_toggled (priv->show_toolbar_button,
2183 MODEST_MSG_EDIT_WINDOW (self));
2186 g_return_if_reached ();
2190 ModestMsgEditFormatState *
2191 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
2193 ModestMsgEditFormatState *format_state = NULL;
2194 ModestMsgEditWindowPrivate *priv;
2195 WPTextBufferFormat *buffer_format;
2197 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
2199 buffer_format = g_new0 (WPTextBufferFormat, 1);
2200 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2202 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
2204 format_state = g_new0 (ModestMsgEditFormatState, 1);
2205 format_state->bold = buffer_format->bold&0x1;
2206 format_state->italics = buffer_format->italic&0x1;
2207 format_state->bullet = buffer_format->bullet&0x1;
2208 format_state->color = buffer_format->color;
2209 format_state->font_size = buffer_format->font_size;
2210 format_state->font_family = wp_get_font_name (buffer_format->font);
2211 format_state->justification = buffer_format->justification;
2212 g_free (buffer_format);
2214 return format_state;
2219 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2220 const ModestMsgEditFormatState *format_state)
2222 ModestMsgEditWindowPrivate *priv;
2223 WPTextBufferFormat *buffer_format;
2224 WPTextBufferFormat *current_format;
2226 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2227 g_return_if_fail (format_state != NULL);
2229 buffer_format = g_new0 (WPTextBufferFormat, 1);
2230 current_format = g_new0 (WPTextBufferFormat, 1);
2232 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2233 gtk_widget_grab_focus (priv->msg_body);
2234 buffer_format->bold = (format_state->bold != FALSE);
2235 buffer_format->italic = (format_state->italics != FALSE);
2236 buffer_format->color = format_state->color;
2237 buffer_format->font_size = format_state->font_size;
2238 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2239 buffer_format->justification = format_state->justification;
2240 buffer_format->bullet = format_state->bullet;
2242 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2244 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2245 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2246 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2247 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2248 buffer_format->cs.font = (buffer_format->font != current_format->font);
2249 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2250 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2252 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2253 if (buffer_format->cs.bold) {
2254 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2255 GINT_TO_POINTER (buffer_format->bold&0x1));
2257 if (buffer_format->cs.italic) {
2258 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2259 GINT_TO_POINTER (buffer_format->italic&0x1));
2261 if (buffer_format->cs.color) {
2262 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2263 GINT_TO_POINTER (&(buffer_format->color)));
2265 if (buffer_format->cs.font_size) {
2266 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2267 GINT_TO_POINTER (buffer_format->font_size));
2269 if (buffer_format->cs.justification) {
2270 switch (buffer_format->justification) {
2271 case GTK_JUSTIFY_LEFT:
2272 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2273 GINT_TO_POINTER(TRUE));
2275 case GTK_JUSTIFY_CENTER:
2276 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2277 GINT_TO_POINTER(TRUE));
2279 case GTK_JUSTIFY_RIGHT:
2280 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2281 GINT_TO_POINTER(TRUE));
2288 if (buffer_format->cs.font) {
2289 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2290 GINT_TO_POINTER (buffer_format->font));
2292 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2293 if (buffer_format->cs.bullet) {
2294 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2295 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2297 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2299 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2301 g_free (buffer_format);
2302 g_free (current_format);
2304 /* Check dimming rules */
2305 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2306 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2310 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2312 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2314 ModestWindowPrivate *parent_priv;
2315 ModestMsgEditWindowPrivate *priv;
2317 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2318 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2320 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2321 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2322 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2323 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2325 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2326 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2327 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2330 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2332 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2333 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2335 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2336 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2338 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2339 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2342 switch (buffer_format->justification)
2344 case GTK_JUSTIFY_LEFT:
2345 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2347 case GTK_JUSTIFY_CENTER:
2348 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2350 case GTK_JUSTIFY_RIGHT:
2351 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2358 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2360 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2361 G_CALLBACK (modest_msg_edit_window_color_button_change),
2363 #ifdef MODEST_TOOLKIT_HILDON2
2364 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2366 gtk_color_button_set_color (GTK_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2368 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2369 G_CALLBACK (modest_msg_edit_window_color_button_change),
2372 if (priv->current_size_index != buffer_format->font_size) {
2376 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2377 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2381 priv->current_size_index = buffer_format->font_size;
2383 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2384 markup = g_strconcat ("<span font_family='Sans'>",
2385 size_text, "</span>", NULL);
2387 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2391 gtk_tree_path_free (path);
2394 #ifdef MODEST_TOOLKIT_HILDON2
2395 if (priv->current_face_index != buffer_format->font) {
2399 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2400 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2404 priv->current_face_index = buffer_format->font;
2405 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2406 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2407 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2414 GtkWidget *new_font_menuitem;
2415 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2416 buffer_format->font))->data);
2417 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2421 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2422 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2423 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2425 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2426 G_CALLBACK (modest_msg_edit_window_font_change),
2428 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2429 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2430 G_CALLBACK (modest_msg_edit_window_font_change),
2435 g_free (buffer_format);
2441 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2443 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2444 ModestMsgEditWindowPrivate *priv;
2445 GtkWidget *dialog = NULL;
2447 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2448 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2450 #ifdef MODEST_TOOLKIT_HILDON2
2451 dialog = hildon_color_chooser_new ();
2452 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2453 g_free (buffer_format);
2455 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2457 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2458 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2461 gtk_widget_destroy (dialog);
2463 dialog = gtk_color_selection_dialog_new (NULL);
2464 GtkWidget *selection;
2466 g_object_get (G_OBJECT (dialog), "color_selection", &selection, NULL);
2467 gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2468 gtk_color_selection_set_previous_color (GTK_COLOR_SELECTION (selection), &(buffer_format->color));
2469 g_free (buffer_format);
2471 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2473 gtk_color_selection_get_current_color (GTK_COLOR_SELECTION(selection), &col);
2474 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2477 gtk_widget_destroy (dialog);
2484 create_stream_for_uri (const gchar* uri)
2489 TnyStream *result = NULL;
2491 GnomeVFSHandle *handle = NULL;
2492 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2493 if (test == GNOME_VFS_OK) {
2494 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2495 /* Streams over OBEX (Bluetooth) are not seekable but
2496 * we expect them to be (we might need to read them
2497 * several times). So if this is a Bluetooth URI just
2498 * read the whole file into memory (this is not a fast
2499 * protocol so we can assume that these files are not
2500 * going to be very big) */
2501 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2502 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2503 TnyStream *memstream = tny_camel_mem_stream_new ();
2504 tny_stream_write_to_stream (vfssstream, memstream);
2505 g_object_unref (vfssstream);
2508 result = vfssstream;
2516 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2519 ModestMsgEditWindowPrivate *priv;
2520 GtkWidget *dialog = NULL;
2522 GSList *uris = NULL;
2523 GSList *uri_node = NULL;
2525 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2527 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2528 _("mcen_ia_select_inline_image_title"),
2529 (GtkWindow *) window,
2530 GTK_FILE_CHOOSER_ACTION_OPEN);
2531 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2533 #ifdef MODEST_TOOLKIT_HILDON2
2534 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2537 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2538 GTK_WINDOW (dialog), GTK_WINDOW (window));
2540 response = gtk_dialog_run (GTK_DIALOG (dialog));
2542 case GTK_RESPONSE_OK:
2544 gchar *current_folder;
2545 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2546 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2547 if (current_folder && current_folder != '\0') {
2549 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2550 current_folder, &err);
2552 g_debug ("Error storing latest used folder: %s", err->message);
2556 g_free (current_folder);
2562 gtk_widget_destroy (dialog);
2564 g_object_ref (window);
2565 /* The operation could take some time so allow the dialog to be closed */
2566 while (gtk_events_pending ())
2567 gtk_main_iteration ();
2569 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2571 GnomeVFSHandle *handle = NULL;
2572 GnomeVFSResult result;
2573 GtkTextIter position;
2574 GtkTextMark *insert_mark;
2576 uri = (const gchar *) uri_node->data;
2577 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2578 if (result == GNOME_VFS_OK) {
2580 GnomeVFSFileInfo *info;
2581 gchar *filename, *basename, *escaped_filename;
2582 TnyMimePart *mime_part;
2584 const gchar *mime_type = NULL;
2585 GnomeVFSURI *vfs_uri;
2586 guint64 stream_size;
2588 gnome_vfs_close (handle);
2589 vfs_uri = gnome_vfs_uri_new (uri);
2591 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2592 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2593 g_free (escaped_filename);
2594 gnome_vfs_uri_unref (vfs_uri);
2595 info = gnome_vfs_file_info_new ();
2597 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2598 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2600 mime_type = gnome_vfs_file_info_get_mime_type (info);
2602 mime_part = tny_platform_factory_new_mime_part
2603 (modest_runtime_get_platform_factory ());
2605 TnyStream *stream = create_stream_for_uri (uri);
2607 if (stream == NULL) {
2609 modest_platform_information_banner (NULL, NULL,
2610 _FM_OPENING_NOT_ALLOWED);
2612 g_object_unref (mime_part);
2613 gnome_vfs_file_info_unref (info);
2617 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2619 content_id = g_strdup_printf ("%d", priv->next_cid);
2620 tny_mime_part_set_content_id (mime_part, content_id);
2621 g_free (content_id);
2624 basename = g_path_get_basename (filename);
2625 tny_mime_part_set_filename (mime_part, basename);
2628 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2630 if (pixbuf != NULL) {
2631 priv->images_size += stream_size;
2632 priv->images_count ++;
2633 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2634 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2635 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2636 tny_mime_part_get_content_id (mime_part), pixbuf);
2637 g_object_unref (pixbuf);
2639 tny_list_prepend (priv->images, (GObject *) mime_part);
2640 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2642 modest_platform_information_banner (NULL, NULL,
2643 _("mail_ib_file_operation_failed"));
2647 g_object_unref (mime_part);
2648 gnome_vfs_file_info_unref (info);
2652 g_object_unref (window);
2656 on_attach_file_response (GtkDialog *dialog,
2660 GSList *uris = NULL;
2662 GnomeVFSFileSize total_size, allowed_size;
2663 ModestMsgEditWindow *window;
2664 ModestMsgEditWindowPrivate *priv;
2669 case GTK_RESPONSE_OK:
2671 gchar *current_folder;
2673 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2674 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2675 if (current_folder && current_folder != '\0') {
2677 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2678 current_folder, &err);
2680 g_debug ("Error storing latest used folder: %s", err->message);
2684 g_free (current_folder);
2691 window = MODEST_MSG_EDIT_WINDOW (user_data);
2692 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2694 /* allowed size is the maximum size - what's already there */
2695 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2696 &att_num, &att_size);
2697 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2700 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2702 const gchar *uri = (const gchar *) uri_node->data;
2705 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2707 if (total_size > allowed_size) {
2708 g_debug ("%s: total size: %u",
2709 __FUNCTION__, (unsigned int)total_size);
2712 allowed_size -= total_size;
2714 g_slist_foreach (uris, (GFunc) g_free, NULL);
2715 g_slist_free (uris);
2717 gtk_widget_destroy (GTK_WIDGET (dialog));
2721 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2723 GtkWidget *dialog = NULL;
2724 ModestMsgEditWindowPrivate *priv;
2727 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2731 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2734 dialog = modest_toolkit_factory_create_file_chooser_dialog (modest_runtime_get_toolkit_factory (),
2735 _("mcen_ia_select_attachment_title"),
2736 (GtkWindow *) window,
2737 GTK_FILE_CHOOSER_ACTION_OPEN);
2738 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2739 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2740 if (conf_folder && conf_folder[0] != '\0') {
2741 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2744 /* Set the default folder to documents folder */
2745 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2746 #ifdef MODEST_TOOLKIT_HILDON2
2749 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2750 ".documents", NULL);
2753 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2754 g_free (docs_folder);
2756 g_free (conf_folder);
2757 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2758 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2759 GTK_WINDOW (dialog), GTK_WINDOW (window));
2761 /* Connect to response & show */
2762 g_signal_connect (dialog, "response",
2763 G_CALLBACK (on_attach_file_response), window);
2764 gtk_widget_show (dialog);
2769 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2771 GnomeVFSFileSize allowed_size)
2774 GnomeVFSHandle *handle = NULL;
2775 ModestMsgEditWindowPrivate *priv;
2776 GnomeVFSResult result;
2777 GnomeVFSFileSize size = 0;
2778 g_return_val_if_fail (window, 0);
2779 g_return_val_if_fail (uri, 0);
2781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2783 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2784 if (result == GNOME_VFS_OK) {
2785 TnyMimePart *mime_part;
2787 const gchar *mime_type = NULL;
2789 gchar *escaped_filename;
2792 GnomeVFSFileInfo *info;
2793 GnomeVFSURI *vfs_uri;
2795 gnome_vfs_close (handle);
2796 vfs_uri = gnome_vfs_uri_new (uri);
2799 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2800 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2801 g_free (escaped_filename);
2802 gnome_vfs_uri_unref (vfs_uri);
2804 info = gnome_vfs_file_info_new ();
2806 if (gnome_vfs_get_file_info (uri,
2808 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2810 mime_type = gnome_vfs_file_info_get_mime_type (info);
2811 mime_part = tny_platform_factory_new_mime_part
2812 (modest_runtime_get_platform_factory ());
2814 /* try to get the attachment's size; this may fail for weird
2815 * file systems, like obex, upnp... */
2816 if (allowed_size != 0 &&
2817 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2819 if (size > allowed_size) {
2820 modest_platform_information_banner (NULL, NULL,
2821 _("mail_ib_error_attachment_size"));
2826 g_debug ("%s: could not get attachment size", __FUNCTION__);
2828 stream = create_stream_for_uri (uri);
2830 if (stream == NULL) {
2832 modest_platform_information_banner (NULL, NULL, _FM_OPENING_NOT_ALLOWED);
2834 g_object_unref (mime_part);
2836 gnome_vfs_file_info_unref (info);
2840 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2841 g_object_unref (stream);
2843 content_id = g_strdup_printf ("%d", priv->next_cid);
2844 tny_mime_part_set_content_id (mime_part, content_id);
2845 g_free (content_id);
2848 basename = g_path_get_basename (filename);
2849 tny_mime_part_set_filename (mime_part, basename);
2852 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2853 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2855 info->size == 0, info->size);
2856 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2857 gtk_widget_show_all (priv->attachments_caption);
2858 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2860 g_object_unref (mime_part);
2861 gnome_vfs_file_info_unref (info);
2868 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2871 ModestMsgEditWindowPrivate *priv;
2874 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2875 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2877 if (att_list == NULL) {
2878 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2879 if (!modest_toolkit_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2880 g_object_unref (att_list);
2884 g_object_ref (att_list);
2887 if (tny_list_get_length (att_list) == 0) {
2888 modest_platform_system_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
2890 gboolean dialog_response;
2891 gchar *message = NULL;
2892 gchar *filename = NULL;
2894 if (tny_list_get_length (att_list) == 1) {
2896 iter = tny_list_create_iterator (att_list);
2897 part = (TnyMimePart *) tny_iterator_get_current (iter);
2898 g_object_unref (iter);
2899 if (TNY_IS_MSG (part)) {
2900 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2902 filename = tny_header_dup_subject (header);
2903 g_object_unref (header);
2905 if (filename == NULL) {
2906 filename = g_strdup (_("mail_va_no_subject"));
2909 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2911 g_object_unref (part);
2913 filename = g_strdup ("");
2915 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2916 "emev_nc_delete_attachments",
2917 tny_list_get_length (att_list)), filename);
2920 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2924 if (dialog_response != GTK_RESPONSE_OK) {
2925 g_object_unref (att_list);
2929 for (iter = tny_list_create_iterator (att_list);
2930 !tny_iterator_is_done (iter);
2931 tny_iterator_next (iter)) {
2932 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2933 const gchar *att_id;
2934 tny_list_remove (priv->attachments, (GObject *) mime_part);
2936 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2938 if (tny_list_get_length (priv->attachments) == 0)
2939 gtk_widget_hide (priv->attachments_caption);
2940 att_id = tny_mime_part_get_content_id (mime_part);
2942 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2944 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2945 g_object_unref (mime_part);
2947 g_object_unref (iter);
2950 g_object_unref (att_list);
2952 /* if the last attachment has been removed, focus the Subject: field */
2953 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2954 gtk_widget_grab_focus (priv->subject_field);
2958 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2961 ModestMsgEditWindowPrivate *priv;
2964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2966 gtk_color_button_get_color (GTK_COLOR_BUTTON(priv->font_color_button), &new_color);
2968 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2970 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2973 #ifndef MODEST_TOOLKIT_HILDON2
2975 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2978 ModestMsgEditWindowPrivate *priv;
2979 gint new_font_index;
2980 ModestMsgEditWindow *window;
2983 window = MODEST_MSG_EDIT_WINDOW (userdata);
2984 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2985 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2987 if (gtk_check_menu_item_get_active (menu_item)) {
2990 label = gtk_bin_get_child (GTK_BIN (menu_item));
2992 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2994 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2995 GINT_TO_POINTER(new_font_index)))
2996 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2998 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2999 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
3000 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3007 font_size_clicked (GtkToolButton *button,
3008 ModestMsgEditWindow *window)
3010 #ifdef MODEST_TOOLKIT_HILDON2
3011 ModestMsgEditWindowPrivate *priv;
3012 GtkWidget *selector, *dialog;
3014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3016 selector = hildon_touch_selector_new ();
3017 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
3018 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
3020 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3021 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3022 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
3024 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3028 WPTextBufferFormat format;
3030 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3032 memset (&format, 0, sizeof (format));
3033 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
3035 format.cs.font_size = TRUE;
3036 format.cs.text_position = TRUE;
3037 format.cs.font = TRUE;
3038 format.font_size = new_index;
3039 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
3041 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
3042 GINT_TO_POINTER (new_index)))
3043 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3045 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3046 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
3047 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
3048 size_text, "</span>", NULL);
3050 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
3054 gtk_widget_destroy (dialog);
3056 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3060 #ifdef MODEST_TOOLKIT_HILDON2
3062 font_face_clicked (GtkToolButton *button,
3063 ModestMsgEditWindow *window)
3065 ModestMsgEditWindowPrivate *priv;
3066 GtkWidget *selector, *dialog;
3067 GtkCellRenderer *renderer;
3069 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3071 selector = hildon_touch_selector_new ();
3072 renderer = gtk_cell_renderer_text_new ();
3073 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
3074 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
3075 renderer, "family", 0, "text", 0, NULL);
3076 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
3078 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
3079 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
3080 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
3082 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
3083 gint new_font_index;
3087 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
3088 path = gtk_tree_path_new_from_indices (new_font_index, -1);
3089 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
3093 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
3095 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
3096 GINT_TO_POINTER(new_font_index)))
3097 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
3099 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
3100 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
3102 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
3106 gtk_tree_path_free (path);
3109 gtk_widget_destroy (dialog);
3111 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
3116 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
3119 ModestMsgEditWindowPrivate *priv = NULL;
3120 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3122 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3123 if (!priv->update_caption_visibility)
3126 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
3128 gtk_widget_show (priv->cc_caption);
3130 gtk_widget_hide (priv->cc_caption);
3132 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
3136 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
3139 ModestMsgEditWindowPrivate *priv = NULL;
3140 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3142 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3143 if (!priv->update_caption_visibility)
3146 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
3148 gtk_widget_show (priv->bcc_caption);
3150 gtk_widget_hide (priv->bcc_caption);
3152 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
3156 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
3157 ModestRecptEditor *editor)
3159 ModestMsgEditWindowPrivate *priv;
3161 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3162 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
3164 /* we check for low-mem; in that case, show a warning, and don't allow
3165 * for the addressbook
3167 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3170 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3172 if (editor == NULL) {
3173 GtkWidget *view_focus, *parent;
3174 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
3176 /* This code should be kept in sync with ModestRecptEditor. The
3177 textview inside the recpt editor is the one that really gets the
3178 focus. As it's inside a scrolled window, and this one inside the
3179 hbox recpt editor inherits from, we'll need to go up in the
3180 hierarchy to know if the text view is part of the recpt editor
3181 or if it's a different text entry */
3182 parent = gtk_widget_get_parent (view_focus);
3183 if (parent && MODEST_IS_RECPT_EDITOR (parent))
3184 editor = MODEST_RECPT_EDITOR (parent);
3187 editor = MODEST_RECPT_EDITOR (priv->to_field);
3190 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
3194 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
3196 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3198 modest_msg_edit_window_open_addressbook (window, NULL);
3202 modest_msg_edit_window_show_toolbar (ModestWindow *self,
3203 gboolean show_toolbar)
3205 ModestWindowPrivate *parent_priv;
3206 ModestMsgEditWindowPrivate *priv;
3208 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
3209 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3210 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3212 /* We can not just use the code of
3213 modest_msg_edit_window_setup_toolbar because it has a
3214 mixture of both initialization and creation code. */
3216 gint current_format;
3217 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3218 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3219 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3220 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3222 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3225 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3227 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, show_toolbar, NULL);
3228 if (modest_togglable_get_active (priv->show_toolbar_button) != show_toolbar) {
3229 modest_togglable_set_active (priv->show_toolbar_button, show_toolbar);
3234 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3235 TnyHeaderFlags priority_flags)
3237 ModestMsgEditWindowPrivate *priv;
3238 ModestWindowPrivate *parent_priv;
3240 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3243 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3245 if (priv->priority_flags != priority_flags) {
3246 GtkAction *priority_action = NULL;
3248 priv->priority_flags = priority_flags;
3250 switch (priority_flags) {
3251 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3252 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3253 MODEST_HEADER_ICON_HIGH,
3254 #ifdef MODEST_TOOLKIT_HILDON2
3255 HILDON_ICON_SIZE_SMALL
3257 GTK_ICON_SIZE_BUTTON
3260 gtk_widget_show (priv->priority_icon);
3261 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3262 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3264 case TNY_HEADER_FLAG_LOW_PRIORITY:
3265 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3266 MODEST_HEADER_ICON_LOW,
3267 #ifdef MODEST_TOOLKIT_HILDON2
3268 HILDON_ICON_SIZE_SMALL
3270 GTK_ICON_SIZE_BUTTON
3273 gtk_widget_show (priv->priority_icon);
3274 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3275 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3278 gtk_widget_hide (priv->priority_icon);
3279 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3280 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3283 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3284 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3286 gtk_widget_queue_resize (priv->subject_box);
3290 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3293 ModestMsgEditWindowPrivate *priv;
3294 ModestWindowPrivate *parent_priv;
3295 gint current_format;
3297 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3299 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3302 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3303 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3305 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3307 if (current_format != file_format) {
3308 switch (file_format) {
3309 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3310 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3311 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3312 update_signature (window, priv->last_from_account, priv->last_from_account);
3313 if (parent_priv->toolbar)
3314 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3315 MODEST_MSG_EDIT_WINDOW (window));
3317 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3320 response = modest_platform_run_confirmation_dialog (NULL, _("emev_nc_formatting_lost"));
3321 if (response == GTK_RESPONSE_OK) {
3322 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3323 if (parent_priv->toolbar)
3324 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3325 MODEST_MSG_EDIT_WINDOW (window));
3327 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3328 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3333 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3334 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3335 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3340 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3342 #ifdef MODEST_TOOLKIT_HILDON2
3344 ModestMsgEditWindowPrivate *priv;
3345 WPTextBufferFormat oldfmt, fmt;
3346 gint old_position = 0;
3350 GdkColor *color = NULL;
3351 gboolean bold, bold_set, italic, italic_set;
3352 gboolean underline, underline_set;
3353 gboolean strikethrough, strikethrough_set;
3354 gboolean position_set;
3355 gboolean font_size_set, font_set, color_set;
3358 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3359 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3361 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3362 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3363 GTK_WINDOW(dialog), GTK_WINDOW (window));
3365 /* First we get the currently selected font information */
3366 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3368 switch (oldfmt.text_position) {
3369 case TEXT_POSITION_NORMAL:
3372 case TEXT_POSITION_SUPERSCRIPT:
3380 g_object_set (G_OBJECT (dialog),
3381 "bold", oldfmt.bold != FALSE,
3382 "bold-set", !oldfmt.cs.bold,
3383 "underline", oldfmt.underline != FALSE,
3384 "underline-set", !oldfmt.cs.underline,
3385 "italic", oldfmt.italic != FALSE,
3386 "italic-set", !oldfmt.cs.italic,
3387 "strikethrough", oldfmt.strikethrough != FALSE,
3388 "strikethrough-set", !oldfmt.cs.strikethrough,
3389 "color", &oldfmt.color,
3390 "color-set", !oldfmt.cs.color,
3391 "size", wp_font_size[oldfmt.font_size],
3392 "size-set", !oldfmt.cs.font_size,
3393 "position", old_position,
3394 "position-set", !oldfmt.cs.text_position,
3395 "family", wp_get_font_name (oldfmt.font),
3396 "family-set", !oldfmt.cs.font,
3399 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3400 GTK_WINDOW (dialog), GTK_WINDOW (window));
3401 gtk_widget_show_all (dialog);
3402 priv->font_dialog = dialog;
3403 response = gtk_dialog_run (GTK_DIALOG (dialog));
3404 priv->font_dialog = NULL;
3405 if (response == GTK_RESPONSE_OK) {
3407 g_object_get( dialog,
3409 "bold-set", &bold_set,
3410 "underline", &underline,
3411 "underline-set", &underline_set,
3413 "italic-set", &italic_set,
3414 "strikethrough", &strikethrough,
3415 "strikethrough-set", &strikethrough_set,
3417 "color-set", &color_set,
3419 "size-set", &font_size_set,
3420 "family", &font_name,
3421 "family-set", &font_set,
3422 "position", &position,
3423 "position-set", &position_set,
3428 if (response == GTK_RESPONSE_OK) {
3429 memset(&fmt, 0, sizeof(fmt));
3435 fmt.italic = italic;
3436 fmt.cs.italic = TRUE;
3438 if (underline_set) {
3439 fmt.underline = underline;
3440 fmt.cs.underline = TRUE;
3442 if (strikethrough_set) {
3443 fmt.strikethrough = strikethrough;
3444 fmt.cs.strikethrough = TRUE;
3449 ? TEXT_POSITION_NORMAL
3450 : ( ( position == 1 )
3451 ? TEXT_POSITION_SUPERSCRIPT
3452 : TEXT_POSITION_SUBSCRIPT );
3453 fmt.cs.text_position = TRUE;
3454 fmt.font_size = oldfmt.font_size;
3458 fmt.cs.color = TRUE;
3461 fmt.font = wp_get_font_index(font_name,
3466 if (font_size_set) {
3467 fmt.cs.font_size = TRUE;
3468 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3470 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3471 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3473 gtk_widget_destroy (dialog);
3475 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3480 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3482 ModestMsgEditWindowPrivate *priv;
3483 ModestWindowPrivate *parent_priv;
3484 gboolean was_rich_text, is_rich_text;
3486 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3487 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3488 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3490 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3492 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3494 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3496 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3497 on_show_toolbar_button_toggled (priv->show_toolbar_button,
3498 MODEST_MSG_EDIT_WINDOW (window));
3501 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3502 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3506 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3508 ModestMsgEditWindowPrivate *priv;
3510 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3513 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3515 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3516 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3521 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3523 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3525 priv->can_undo = can_undo;
3529 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3531 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3533 priv->can_redo = can_redo;
3537 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3539 ModestMsgEditWindowPrivate *priv;
3540 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3543 return priv->can_undo;
3547 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3549 ModestMsgEditWindowPrivate *priv;
3550 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3551 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3553 return priv->can_redo;
3558 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3561 GtkTextIter match_start, match_end;
3563 if (image_id == NULL)
3566 gtk_text_buffer_get_start_iter (buffer, &iter);
3568 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3569 GSList *tags = gtk_text_iter_get_tags (&match_start);
3571 for (node = tags; node != NULL; node = g_slist_next (node)) {
3572 GtkTextTag *tag = (GtkTextTag *) node->data;
3573 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3574 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3575 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3577 offset = gtk_text_iter_get_offset (&match_start);
3578 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3579 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3583 gtk_text_iter_forward_char (&iter);
3588 message_is_empty (ModestMsgEditWindow *window)
3590 ModestMsgEditWindowPrivate *priv = NULL;
3592 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3595 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3596 * so we can ignore markup.
3598 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3601 count = gtk_text_buffer_get_char_count (buf);
3607 msg_body_focus (GtkWidget *focus,
3608 GdkEventFocus *event,
3612 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3613 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3614 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3619 recpt_field_changed (GtkTextBuffer *buffer,
3620 ModestMsgEditWindow *editor)
3622 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3623 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3627 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3629 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3630 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3634 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3637 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3638 GtkTextBuffer *buffer;
3640 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3641 gtk_text_buffer_set_modified (buffer, modified);
3642 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3643 gtk_text_buffer_set_modified (buffer, modified);
3644 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3645 gtk_text_buffer_set_modified (buffer, modified);
3646 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3650 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3652 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3653 const char *account_name;
3654 GtkTextBuffer *buffer;
3656 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3657 if (gtk_text_buffer_get_modified (buffer))
3659 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3660 if (gtk_text_buffer_get_modified (buffer))
3662 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3663 if (gtk_text_buffer_get_modified (buffer))
3665 if (gtk_text_buffer_get_modified (priv->text_buffer))
3668 account_name = modest_selector_get_active_id (priv->from_field);
3669 if (priv->original_mailbox) {
3670 if (!account_name || strcmp (account_name, priv->original_mailbox))
3672 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3683 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3685 ModestMsgEditWindowPrivate *priv = NULL;
3686 GSList *address_list = NULL;
3687 gboolean no_to, no_cc, no_bcc;
3689 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3690 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3692 /* check if there's no recipient added */
3693 no_to = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)));
3694 no_cc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field)));
3695 no_bcc = modest_text_utils_no_recipient (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field)));
3698 if (no_to && no_cc && no_bcc) {
3699 /* no recipient contents, then select contacts */
3700 modest_msg_edit_window_open_addressbook (window, NULL);
3705 g_object_ref (window);
3706 if (!no_to && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3707 (add_to_addressbook) ? &address_list : NULL)) {
3708 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3709 g_object_unref (window);
3712 if (!no_cc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3713 (add_to_addressbook) ? &address_list : NULL)) {
3714 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3715 g_object_unref (window);
3718 if (!no_bcc && !modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3719 (add_to_addressbook) ? &address_list : NULL)) {
3720 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3721 g_object_unref (window);
3725 /* Add contacts to address book */
3726 if (add_to_addressbook && address_list)
3727 modest_address_book_add_address_list (address_list);
3729 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3730 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3731 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3732 g_object_unref (window);
3739 modest_msg_edit_window_add_to_contacts (ModestMsgEditWindow *self)
3741 GSList *recipients = NULL;
3742 ModestMsgEditWindowPrivate *priv;
3743 gchar *joined, *after_remove, *to, *cc, *bcc;
3745 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3747 /* First of all check names */
3748 if (!modest_msg_edit_window_check_names (self, FALSE))
3751 if (!modest_msg_edit_window_has_pending_addresses (self))
3754 /* Don't add the from obviously */
3755 to = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->to_field));
3756 cc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->cc_field));
3757 bcc = g_strdup (modest_recpt_editor_get_recipients ((ModestRecptEditor *) priv->bcc_field));
3759 joined = modest_text_utils_join_addresses (NULL, to, cc, bcc);
3764 after_remove = modest_text_utils_remove_duplicate_addresses (joined);
3767 recipients = modest_text_utils_split_addresses_list (after_remove);
3768 g_free (after_remove);
3771 /* Offer the user to add recipients to the address book */
3772 modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self);
3773 g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);
3778 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3779 ModestMsgEditWindow *window)
3781 modest_msg_edit_window_offer_attach_file (window);
3785 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3787 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3789 return priv->clipboard_text;
3793 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3795 ModestMsgEditWindow *window)
3797 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3798 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3801 /* It could happen that the window was already closed */
3802 if (!GTK_WIDGET_VISIBLE (window))
3805 g_object_ref (window);
3806 text = gtk_clipboard_wait_for_text (selection_clipboard);
3808 if (priv->clipboard_text != NULL) {
3809 g_free (priv->clipboard_text);
3811 priv->clipboard_text = text;
3813 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3815 g_object_unref (window);
3818 static gboolean clipboard_owner_change_idle (gpointer userdata)
3820 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3821 ModestMsgEditWindowPrivate *priv;
3823 gdk_threads_enter ();
3824 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3827 priv->clipboard_owner_idle = 0;
3828 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3829 gdk_threads_leave ();
3835 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3837 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3838 if (priv->clipboard_owner_idle == 0) {
3839 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3840 clipboard_owner_change_idle,
3841 g_object_ref (window),
3847 subject_field_move_cursor (GtkEntry *entry,
3848 GtkMovementStep step,
3853 /* It could happen that the window was already closed */
3854 if (!GTK_WIDGET_VISIBLE (window))
3857 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3861 update_window_title (ModestMsgEditWindow *window)
3863 ModestMsgEditWindowPrivate *priv = NULL;
3864 const gchar *subject;
3866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3867 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3868 if (subject == NULL || subject[0] == '\0')
3869 subject = _("mail_va_new_email");
3871 modest_window_set_title (MODEST_WINDOW (window), subject);
3877 body_insert_text (GtkTextBuffer *buffer,
3878 GtkTextIter *location,
3881 ModestMsgEditWindow *window)
3883 GtkTextIter end_iter;
3890 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3892 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3894 offset = gtk_text_iter_get_offset (&end_iter);
3895 line = gtk_text_iter_get_line (&end_iter);
3899 while (text_offset < text + len) {
3900 if (*text_offset == '\n')
3902 if (text_lines + line >= MAX_BODY_LINES) {
3903 len = text_offset - text;
3909 utf8_len = g_utf8_strlen (text, len);
3911 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3912 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3913 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3918 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3920 /* Prevent endless recursion */
3921 result = g_strndup (text, utf8_end - text);
3922 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3923 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3924 (gpointer) result, (gpointer) (utf8_end - text),
3926 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3930 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3931 if (priv->max_chars_banner == NULL) {
3932 #ifdef MODEST_TOOLKIT_HILDON2
3933 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3934 _CS_MAXIMUM_CHARACTERS_REACHED);
3935 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3942 subject_field_changed (GtkEditable *editable,
3943 ModestMsgEditWindow *window)
3945 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3946 update_window_title (window);
3947 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3948 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3949 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3952 subject_field_insert_text (GtkEditable *editable,
3954 gint new_text_length,
3956 ModestMsgEditWindow *window)
3958 GString *result = g_string_new ("");
3960 gint result_len = 0;
3961 const gchar *entry_text = NULL;
3964 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3965 old_length = g_utf8_strlen (entry_text, -1);
3967 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3968 gunichar c = g_utf8_get_char_validated (current, 8);
3969 /* Invalid unichar, stop */
3975 result = g_string_append_unichar (result, c);
3979 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3980 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3983 /* Prevent endless recursion */
3984 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3985 g_signal_emit_by_name (editable, "insert-text",
3986 (gpointer) result->str, (gpointer) result->len,
3987 (gpointer) position, (gpointer) window);
3988 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3992 if (result_len + old_length > 1000) {
3993 modest_platform_system_banner (GTK_WIDGET (window), NULL,
3994 _CS_MAXIMUM_CHARACTERS_REACHED);
3996 g_string_free (result, TRUE);
4000 modest_msg_edit_window_toggle_isearch_toolbar (ModestMsgEditWindow *window,
4003 ModestMsgEditWindowPrivate *priv = NULL;
4005 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4006 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4008 gtk_widget_set_no_show_all (priv->isearch_toolbar, FALSE);
4011 gtk_widget_show_all (priv->isearch_toolbar);
4012 modest_isearch_toolbar_highlight_entry (MODEST_ISEARCH_TOOLBAR (priv->isearch_toolbar), TRUE);
4014 gtk_widget_hide_all (priv->isearch_toolbar);
4015 gtk_widget_grab_focus (priv->msg_body);
4020 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
4022 GtkTextIter *match_start,
4023 GtkTextIter *match_end)
4025 GtkTextIter end_iter;
4026 gchar *str_casefold;
4029 gchar *range_casefold;
4032 gboolean result = FALSE;
4039 gtk_text_iter_forward_to_end (&end_iter);
4041 str_casefold = g_utf8_casefold (str, -1);
4042 str_chars_n = strlen (str);
4044 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
4045 range_casefold = g_utf8_casefold (range_text, -1);
4046 range_chars_n = strlen (range_casefold);
4048 if (range_chars_n < str_chars_n) {
4049 g_free (str_casefold);
4050 g_free (range_text);
4051 g_free (range_casefold);
4055 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
4056 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
4057 if (!g_utf8_collate (range_subtext, str_casefold)) {
4058 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
4060 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
4061 match_start, match_end, NULL)) {
4062 g_debug ("Matched string with collate, but not matched in model");
4064 g_free (found_text);
4066 g_free (range_subtext);
4070 g_free (str_casefold);
4071 g_free (range_text);
4072 g_free (range_casefold);
4079 modest_msg_edit_window_isearch_toolbar_search (GtkWidget *widget,
4080 ModestMsgEditWindow *window)
4082 const gchar *current_search = NULL;
4083 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4085 GtkTextIter selection_start, selection_end;
4086 GtkTextIter match_start, match_end;
4087 gboolean continue_search = FALSE;
4089 if (message_is_empty (window)) {
4090 g_free (priv->last_search);
4091 priv->last_search = NULL;
4092 modest_platform_system_banner (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
4096 current_search = modest_isearch_toolbar_get_search (MODEST_ISEARCH_TOOLBAR (widget));
4097 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
4098 g_free (priv->last_search);
4099 priv->last_search = NULL;
4100 /* Information banner about empty search */
4101 modest_platform_system_banner (NULL, NULL, _CS_FIND_REP_ENTER_TEXT);
4105 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
4106 continue_search = TRUE;
4108 g_free (priv->last_search);
4109 priv->last_search = g_strdup (current_search);
4112 if (continue_search) {
4113 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
4114 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
4115 &match_start, &match_end);
4117 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_COMPLETE);
4119 GtkTextIter buffer_start;
4120 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
4121 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
4122 &match_start, &match_end);
4124 modest_platform_system_banner (NULL, NULL, _HL_IB_FIND_NO_MATCHES);
4127 /* Mark as selected the string found in search */
4129 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
4130 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
4131 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
4133 g_free (priv->last_search);
4134 priv->last_search = NULL;
4139 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
4141 ModestMsgEditWindowPrivate *priv;
4143 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4148 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
4151 ModestMsgEditWindowPrivate *priv;
4153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
4158 modest_msg_edit_window_isearch_toolbar_close (GtkWidget *widget,
4159 ModestMsgEditWindow *window)
4161 modest_msg_edit_window_toggle_isearch_toolbar (window, FALSE);
4165 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
4168 ModestMsgEditWindowPrivate *priv;
4169 TnyHeader *header = NULL;
4171 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4172 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
4174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4176 if (priv->draft_msg != NULL) {
4177 g_object_unref (priv->draft_msg);
4180 if (draft != NULL) {
4181 g_object_ref (draft);
4182 header = tny_msg_get_header (draft);
4183 if (priv->msg_uid) {
4184 g_free (priv->msg_uid);
4185 priv->msg_uid = NULL;
4187 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
4190 priv->draft_msg = draft;
4194 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
4195 GtkTextIter *start, GtkTextIter *end,
4198 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
4199 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
4202 if (tag == NULL) return;
4203 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
4204 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
4205 replace_with_images (window, priv->images);
4210 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
4213 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4215 g_return_if_fail (TNY_IS_MIME_PART (part));
4216 tny_list_prepend (priv->attachments, (GObject *) part);
4217 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
4218 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
4219 gtk_widget_show_all (priv->attachments_caption);
4220 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
4224 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
4226 ModestMsgEditWindowPrivate *priv;
4228 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
4229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4231 return priv->msg_uid;
4235 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
4236 ModestMsgEditWindowWidgetType widget_type)
4238 ModestMsgEditWindowPrivate *priv;
4240 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
4241 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
4243 switch (widget_type) {
4244 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
4245 return priv->msg_body;
4247 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
4248 return priv->to_field;
4250 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
4251 return priv->cc_field;
4253 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
4254 return priv->bcc_field;
4256 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
4257 return priv->subject_field;
4259 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
4260 return priv->attachments_view;
4268 remove_tags (WPTextBuffer *buffer)
4270 GtkTextIter start, end;
4272 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4273 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4275 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4279 on_account_removed (TnyAccountStore *account_store,
4280 TnyAccount *account,
4283 /* Do nothing if it's a store account, because we use the
4284 transport to send the messages */
4285 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4286 const gchar *parent_acc = NULL;
4287 const gchar *our_acc = NULL;
4289 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4290 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4291 /* Close this window if I'm showing a message of the removed account */
4292 if (strcmp (parent_acc, our_acc) == 0)
4293 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4298 update_signature (ModestMsgEditWindow *self,
4299 const gchar *old_account,
4300 const gchar *new_account)
4302 ModestMsgEditWindowPrivate *priv;
4303 gboolean has_old_signature, has_new_signature;
4305 ModestAccountMgr *mgr;
4308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4310 gtk_text_buffer_begin_user_action (priv->text_buffer);
4312 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4313 mgr = modest_runtime_get_account_mgr ();
4317 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4318 if (has_old_signature) {
4319 GtkTextIter match_start, match_end;
4321 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4322 seems that the search has some problems
4323 with the blank space at the end */
4324 if (gtk_text_iter_forward_search (&iter, "--",
4325 GTK_TEXT_SEARCH_TEXT_ONLY,
4326 &match_start, NULL, NULL)) {
4327 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4328 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4330 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4331 &match_start, &match_end, NULL)) {
4335 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4340 priv->last_from_account = modest_selector_get_active_id (priv->from_field);
4341 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4342 if (has_new_signature) {
4345 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4346 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4348 is_rich = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
4350 WPTextBufferFormat *fmt;
4351 GdkColor style_color;
4352 if (!gtk_style_lookup_color (GTK_WIDGET (self)->style, "SecondaryTextColor", &style_color)) {
4353 gdk_color_parse ("grey", &style_color);
4355 fmt = g_new0 (WPTextBufferFormat, 1);
4356 fmt->color = style_color;
4357 fmt->cs.color = 0x1;
4358 wp_text_buffer_insert_with_attribute (WP_TEXT_BUFFER (priv->text_buffer), &iter,
4362 g_free (full_signature);
4364 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4368 gtk_text_buffer_end_user_action (priv->text_buffer);
4371 static void update_branding (ModestMsgEditWindow *self,
4372 const gchar *new_account)
4374 ModestMsgEditWindowPrivate *priv;
4375 ModestAccountMgr *mgr;
4376 const GdkPixbuf *new_icon = NULL;
4377 gchar *new_label = NULL;
4378 gboolean show = FALSE;
4380 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4382 mgr = modest_runtime_get_account_mgr ();
4384 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4386 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4387 gtk_widget_show (priv->brand_icon);
4390 gtk_widget_hide (priv->brand_icon);
4393 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4394 gtk_widget_show (priv->brand_label);
4398 gtk_widget_hide (priv->brand_label);
4402 gtk_widget_show (priv->brand_container);
4404 gtk_widget_hide (priv->brand_container);
4408 from_field_changed (GtkWidget *button,
4409 ModestMsgEditWindow *self)
4411 ModestMsgEditWindowPrivate *priv;
4412 gchar *old_account, *new_account;
4414 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4416 old_account = priv->last_from_account;
4417 new_account = modest_selector_get_active_id (priv->from_field);
4420 g_warning ("%s, could not get the new account", __FUNCTION__);
4424 /* If the From is the same do nothing */
4425 if (old_account && new_account && !strcmp (old_account, new_account))
4428 priv->last_from_account = new_account;
4430 update_signature (self, old_account, new_account);
4431 update_branding (self, new_account);
4435 typedef struct _MessageSettingsHelper {
4436 ModestMsgEditWindow *window;
4437 GSList *priority_group;
4438 GSList *format_group;
4439 GtkToggleButton *current_priority;
4440 GtkToggleButton *current_format;
4441 } MessageSettingsHelper;
4444 on_priority_toggle (GtkToggleButton *button,
4445 MessageSettingsHelper *helper)
4448 ModestMsgEditWindowPrivate *priv;
4450 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4451 if (gtk_toggle_button_get_active (button)) {
4453 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4454 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4455 if ((node_button != button) &&
4456 gtk_toggle_button_get_active (node_button)) {
4457 gtk_toggle_button_set_active (node_button, FALSE);
4460 helper->current_priority = button;
4462 gboolean found = FALSE;
4463 /* If no one is active, activate it again */
4464 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4465 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4466 if (gtk_toggle_button_get_active (node_button)) {
4472 gtk_toggle_button_set_active (button, TRUE);
4478 on_format_toggle (GtkToggleButton *button,
4479 MessageSettingsHelper *helper)
4482 ModestMsgEditWindowPrivate *priv;
4484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4485 if (gtk_toggle_button_get_active (button)) {
4487 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4488 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4489 if ((node_button != button) &&
4490 gtk_toggle_button_get_active (node_button)) {
4491 gtk_toggle_button_set_active (node_button, FALSE);
4494 helper->current_format = button;
4496 gboolean found = FALSE;
4497 /* If no one is active, activate it again */
4498 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4499 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4500 if (gtk_toggle_button_get_active (node_button)) {
4506 gtk_toggle_button_set_active (button, TRUE);
4513 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4518 GtkWidget *priority_hbox;
4519 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4520 GtkWidget *captioned;
4521 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4522 GtkWidget *format_hbox;
4523 GtkWidget *html_toggle, *text_toggle;
4524 ModestMsgEditWindowPrivate *priv;
4525 MessageSettingsHelper helper = {0,};
4527 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4528 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4529 helper.window = window;
4530 helper.priority_group = NULL;
4531 helper.format_group = NULL;
4533 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4534 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4536 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4537 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4538 _HL_DONE, GTK_RESPONSE_ACCEPT, NULL);
4539 vbox = gtk_vbox_new (FALSE, 0);
4540 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4541 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4542 gtk_container_add (GTK_CONTAINER (align), vbox);
4543 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4544 gtk_widget_show (align);
4545 gtk_widget_show (vbox);
4547 /* Priority toggles */
4548 priority_hbox = gtk_hbox_new (TRUE, 0);
4549 #ifdef MODEST_TOOLKIT_HILDON2
4550 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4552 high_toggle = gtk_toggle_button_new ();
4554 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4555 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4556 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4557 #ifdef MODEST_TOOLKIT_HILDON2
4558 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4560 medium_toggle = gtk_toggle_button_new ();
4562 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4563 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4564 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4565 #ifdef MODEST_TOOLKIT_HILDON2
4566 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4568 low_toggle = gtk_toggle_button_new ();
4570 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4571 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4572 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4573 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4574 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4575 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4576 gtk_widget_show_all (priority_hbox);
4577 captioned = modest_toolkit_utils_create_captioned (title_sizegroup, value_sizegroup,
4578 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4579 gtk_widget_show (captioned);
4580 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4582 /* format toggles */
4583 format_hbox = gtk_hbox_new (TRUE, 0);
4584 #ifdef MODEST_TOOLKIT_HILDON2
4585 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4587 html_toggle = gtk_toggle_button_new ();
4589 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4590 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4591 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4592 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4593 #ifdef MODEST_TOOLKIT_HILDON2
4594 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4596 text_toggle = gtk_toggle_button_new ();
4598 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4599 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4600 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4601 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4602 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4603 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4604 gtk_widget_show_all (format_hbox);
4605 gtk_widget_show (format_hbox);
4606 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4609 g_object_unref (title_sizegroup);
4610 g_object_unref (value_sizegroup);
4612 /* Set current values */
4613 switch (priv->priority_flags) {
4614 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4615 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4616 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4618 case TNY_HEADER_FLAG_LOW_PRIORITY:
4619 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4620 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4623 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4624 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4628 switch (modest_msg_edit_window_get_format (window)) {
4629 case MODEST_MSG_EDIT_FORMAT_TEXT:
4630 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4631 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4633 case MODEST_MSG_EDIT_FORMAT_HTML:
4635 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4636 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4640 /* Signal connects */
4641 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4642 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4643 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4644 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4645 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4647 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4648 GTK_WINDOW (dialog), GTK_WINDOW (window));
4650 /* Save settings if the user clicked on done */
4651 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4652 TnyHeaderFlags flags;
4653 ModestMsgEditFormat old_format, new_format;
4655 /* Set priority flags */
4656 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4657 if (priv->priority_flags != flags)
4658 modest_msg_edit_window_set_priority_flags (window, flags);
4660 /* Set edit format */
4661 old_format = modest_msg_edit_window_get_format (window);
4662 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4663 if (old_format != new_format) {
4664 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4665 modest_msg_edit_window_set_file_format (window, file_format);
4669 gtk_widget_destroy (dialog);
4670 g_slist_free (helper.priority_group);
4674 on_message_settings (GtkAction *action,
4675 ModestMsgEditWindow *window)
4677 modest_msg_edit_window_show_msg_settings_dialog (window);
4681 on_show_toolbar_button_toggled (GtkWidget *button,
4682 ModestMsgEditWindow *window)
4684 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4686 modest_msg_edit_window_show_toolbar (MODEST_WINDOW (window),
4687 modest_togglable_get_active (button));
4691 on_cc_button_toggled (GtkWidget *button,
4692 ModestMsgEditWindow *window)
4694 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4696 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4697 modest_togglable_get_active (button));
4701 on_bcc_button_toggled (GtkWidget *button,
4702 ModestMsgEditWindow *window)
4704 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4706 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4707 modest_togglable_get_active (button));
4711 setup_menu (ModestMsgEditWindow *self)
4713 ModestMsgEditWindowPrivate *priv = NULL;
4715 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4719 /* Settings menu buttons */
4720 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4721 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_check_names),
4723 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL,
4724 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_add_to_contacts),
4725 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts));
4726 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4727 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_undo),
4728 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4730 priv->cc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4731 _("mcen_me_editor_showcc"));
4732 modest_togglable_set_active (priv->cc_button,
4734 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->cc_button, NULL);
4735 gtk_widget_show (priv->cc_button);
4736 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4737 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4739 priv->bcc_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4740 _("mcen_me_editor_showbcc"));
4741 gtk_widget_show (priv->bcc_button);
4742 modest_togglable_set_active (priv->bcc_button,
4744 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->bcc_button,
4746 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4747 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4749 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4750 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4751 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4752 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4753 MODEST_WINDOW_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4755 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4756 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4757 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4758 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_message_settings"), NULL,
4759 MODEST_WINDOW_MENU_CALLBACK (on_message_settings),
4761 modest_window_add_to_menu (MODEST_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4762 MODEST_WINDOW_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4765 priv->show_toolbar_button = modest_toolkit_factory_create_check_menu (modest_runtime_get_toolkit_factory (),
4766 _("mcen_bd_show_toolbar"));
4767 modest_togglable_set_active (priv->show_toolbar_button,
4769 modest_window_add_item_to_menu (MODEST_WINDOW (self), priv->show_toolbar_button,
4770 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_show_toolbar));
4771 gtk_widget_show (priv->show_toolbar_button);
4772 g_signal_connect (G_OBJECT (priv->show_toolbar_button), "toggled",
4773 G_CALLBACK (on_show_toolbar_button_toggled), (gpointer) self);
4778 emit_open_addressbook (GtkButton *button,
4779 ModestRecptEditor *editor)
4781 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4785 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4786 const gchar *label, GtkWidget *control)
4788 GtkWidget *abook_button;
4791 GtkWidget *label_widget;
4793 box = gtk_hbox_new (FALSE, 0);
4795 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4796 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4798 #ifdef MODEST_TOOLKIT_HILDON2
4799 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4801 abook_button = gtk_button_new ();
4803 label_widget = gtk_label_new (label);
4804 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4805 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4807 gtk_container_add (GTK_CONTAINER (align), abook_button);
4808 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4809 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4810 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4811 if (title_size_group)
4812 gtk_size_group_add_widget (title_size_group, label_widget);
4813 if (value_size_group)
4814 gtk_size_group_add_widget (value_size_group, control);
4816 g_signal_connect (G_OBJECT (abook_button), "clicked",
4817 G_CALLBACK (emit_open_addressbook), control);
4823 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4825 ModestMsgEditWindowPrivate *priv = NULL;
4827 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4829 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4830 priv->max_chars_banner = NULL;
4834 has_pending_addresses (ModestRecptEditor *recpt_editor)
4836 const gchar *recipients = NULL;
4837 GSList *start_indexes = NULL, *end_indexes = NULL;
4838 GSList *current_start, *current_end;
4839 GtkTextBuffer *buffer;
4840 gint offset_delta = 0;
4842 gboolean has_recipients_to_add = FALSE;
4844 recipients = modest_recpt_editor_get_recipients (recpt_editor);
4845 last_length = g_utf8_strlen (recipients, -1);
4846 modest_text_utils_get_addresses_indexes (recipients, &start_indexes, &end_indexes);
4851 current_start = start_indexes;
4852 current_end = end_indexes;
4853 buffer = modest_recpt_editor_get_buffer (recpt_editor);
4855 while (current_start && !has_recipients_to_add) {
4857 gchar *start_ptr, *end_ptr;
4858 gint start_pos, end_pos;
4860 start_pos = (*((gint*) current_start->data)) + offset_delta;
4861 end_pos = (*((gint*) current_end->data)) + offset_delta;
4863 start_ptr = g_utf8_offset_to_pointer (recipients, start_pos);
4864 end_ptr = g_utf8_offset_to_pointer (recipients, end_pos);
4866 address = g_strstrip (g_strndup (start_ptr, end_ptr - start_ptr));
4868 if (modest_text_utils_validate_recipient (address, NULL)) {
4869 if (!modest_address_book_has_address (address)) {
4870 has_recipients_to_add = TRUE;
4873 current_start = g_slist_next (current_start);
4874 current_end = g_slist_next (current_end);
4876 return has_recipients_to_add;
4880 modest_msg_edit_window_has_pending_addresses (ModestMsgEditWindow *self)
4882 ModestMsgEditWindowPrivate *priv = NULL;
4884 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self), FALSE);
4886 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4888 if (!has_pending_addresses ((ModestRecptEditor *) priv->to_field) &&
4889 !has_pending_addresses ((ModestRecptEditor *) priv->cc_field) &&
4890 !has_pending_addresses ((ModestRecptEditor *) priv->bcc_field))
4897 modest_msg_edit_window_set_custom_header_pairs (ModestMsgEditWindow *self,
4898 TnyList *header_pairs)
4900 ModestMsgEditWindowPrivate *priv = NULL;
4902 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
4903 g_return_if_fail (TNY_IS_LIST (header_pairs));
4905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4906 g_object_unref (priv->custom_header_pairs);
4907 priv->custom_header_pairs = tny_list_copy (header_pairs);