1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 4096
98 static gboolean is_wp_text_buffer_started = FALSE;
100 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
101 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
102 static void modest_msg_edit_window_finalize (GObject *obj);
104 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
105 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
106 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
108 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
109 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
110 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
111 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
112 GtkTextIter *start, GtkTextIter *end,
114 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
115 static void body_insert_text (GtkTextBuffer *buffer,
116 GtkTextIter *location,
119 ModestMsgEditWindow *window);
120 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
121 static void subject_field_insert_text (GtkEditable *editable,
123 gint new_text_length,
125 ModestMsgEditWindow *window);
126 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
128 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static void init_window (ModestMsgEditWindow *obj);
168 gboolean scroll_drag_timeout (gpointer userdata);
169 static void correct_scroll (ModestMsgEditWindow *w);
170 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
171 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
172 ModestMsgEditWindow *userdata);
173 static void text_buffer_mark_set (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void on_message_settings (GtkAction *action,
178 ModestMsgEditWindow *window);
179 static void setup_menu (ModestMsgEditWindow *self);
181 static void from_field_changed (HildonPickerButton *button,
182 ModestMsgEditWindow *self);
183 static void font_size_clicked (GtkToolButton *button,
184 ModestMsgEditWindow *window);
185 static void font_face_clicked (GtkToolButton *button,
186 ModestMsgEditWindow *window);
187 static void update_signature (ModestMsgEditWindow *self,
188 const gchar *old_account,
189 const gchar *new_account);
190 static void update_branding (ModestMsgEditWindow *self,
191 const gchar *new_account);
192 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
193 const gchar *label, GtkWidget *control);
194 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
195 static void DEBUG_BUFFER (WPTextBuffer *buffer)
199 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
201 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
202 while (!gtk_text_iter_is_end (&iter)) {
203 GString *output = g_string_new ("");
204 GSList *toggled_tags;
207 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
208 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
209 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
210 GtkTextTag *tag = (GtkTextTag *) node->data;
212 g_object_get (G_OBJECT (tag), "name", &name, NULL);
213 output = g_string_append (output, name);
214 g_string_append (output, " ");
216 output = g_string_append (output, "] OPENED [ ");
217 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
218 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
219 GtkTextTag *tag = (GtkTextTag *) node->data;
221 g_object_get (G_OBJECT (tag), "name", &name, NULL);
222 output = g_string_append (output, name);
223 g_string_append (output, " ");
225 output = g_string_append (output, "]\n");
226 g_debug ("%s", output->str);
227 g_string_free (output, TRUE);
228 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
230 g_debug ("END BUFFER");
234 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
235 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
239 /* static gboolean */
240 /* on_key_pressed (GtkWidget *self, */
241 /* GdkEventKey *event, */
242 /* gpointer user_data); */
244 /* list my signals */
251 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
252 struct _ModestMsgEditWindowPrivate {
254 GtkWidget *header_box;
256 ModestPairList *from_field_protos;
257 GtkWidget *from_field;
258 gchar *last_from_account;
259 gchar *original_account_name;
264 gchar *original_mailbox;
268 GtkWidget *bcc_field;
269 GtkWidget *subject_field;
270 GtkWidget *attachments_view;
271 GtkWidget *priority_icon;
272 GtkWidget *subject_box;
273 GtkWidget *send_button;
275 GtkWidget *cc_caption;
276 GtkWidget *bcc_caption;
277 gboolean update_caption_visibility;
278 GtkWidget *attachments_caption;
280 GtkTextBuffer *text_buffer;
282 GtkWidget *font_size_toolitem;
283 GtkWidget *font_face_toolitem;
284 GtkWidget *font_color_button;
285 GtkWidget *font_color_toolitem;
286 GSList *font_items_group;
287 GtkTreeModel *faces_model;
288 gint current_face_index;
289 GtkWidget *font_tool_button_label;
290 GtkTreeModel *sizes_model;
291 gint current_size_index;
292 GtkWidget *size_tool_button_label;
294 GtkWidget *find_toolbar;
297 GtkWidget *font_dialog;
300 guint correct_scroll_idle;
301 guint scroll_drag_timeout_id;
305 TnyList *attachments;
310 TnyHeaderFlags priority_flags;
312 gboolean can_undo, can_redo;
313 gulong clipboard_change_handler_id;
314 gulong default_clipboard_change_handler_id;
315 gulong account_removed_handler_id;
316 guint clipboard_owner_idle;
317 gchar *clipboard_text;
326 GtkWidget *cc_button;
327 GtkWidget *bcc_button;
329 GtkWidget *max_chars_banner;
331 GtkWidget *brand_icon;
332 GtkWidget *brand_label;
335 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
336 MODEST_TYPE_MSG_EDIT_WINDOW, \
337 ModestMsgEditWindowPrivate))
339 static GtkWindowClass *parent_class = NULL;
341 /* uncomment the following if you have defined any signals */
342 /* static guint signals[LAST_SIGNAL] = {0}; */
345 modest_msg_edit_window_get_type (void)
347 static GType my_type = 0;
349 static const GTypeInfo my_info = {
350 sizeof(ModestMsgEditWindowClass),
351 NULL, /* base init */
352 NULL, /* base finalize */
353 (GClassInitFunc) modest_msg_edit_window_class_init,
354 NULL, /* class finalize */
355 NULL, /* class data */
356 sizeof(ModestMsgEditWindow),
358 (GInstanceInitFunc) modest_msg_edit_window_init,
361 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
362 "ModestMsgEditWindow",
370 save_state (ModestWindow *self)
372 modest_widget_memory_save (modest_runtime_get_conf(),
373 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
378 restore_settings (ModestMsgEditWindow *self)
380 ModestConf *conf = NULL;
382 conf = modest_runtime_get_conf ();
384 /* Dim at start clipboard actions */
385 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
390 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
392 GObjectClass *gobject_class;
393 ModestWindowClass *modest_window_class;
394 gobject_class = (GObjectClass*) klass;
395 modest_window_class = (ModestWindowClass*) klass;
397 parent_class = g_type_class_peek_parent (klass);
398 gobject_class->finalize = modest_msg_edit_window_finalize;
400 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
401 modest_window_class->save_state_func = save_state;
402 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
404 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
408 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
410 ModestMsgEditWindowPrivate *priv;
411 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
413 priv->msg_body = NULL;
414 priv->from_field = NULL;
415 priv->to_field = NULL;
416 priv->cc_field = NULL;
417 priv->bcc_field = NULL;
418 priv->subject_field = NULL;
419 priv->attachments = TNY_LIST (tny_simple_list_new ());
420 priv->images = TNY_LIST (tny_simple_list_new ());
421 priv->images_size = 0;
422 priv->images_count = 0;
425 priv->cc_caption = NULL;
426 priv->bcc_caption = NULL;
427 priv->update_caption_visibility = FALSE;
429 priv->priority_flags = 0;
431 priv->find_toolbar = NULL;
432 priv->last_search = NULL;
434 priv->draft_msg = NULL;
435 priv->outbox_msg = NULL;
436 priv->msg_uid = NULL;
438 priv->can_undo = FALSE;
439 priv->can_redo = FALSE;
440 priv->clipboard_change_handler_id = 0;
441 priv->default_clipboard_change_handler_id = 0;
442 priv->account_removed_handler_id = 0;
443 priv->clipboard_owner_idle = 0;
444 priv->clipboard_text = NULL;
447 priv->scroll_drag_timeout_id = 0;
448 priv->correct_scroll_idle = 0;
449 priv->last_upper = 0.0;
451 priv->font_dialog = NULL;
452 priv->app_menu = NULL;
454 priv->references = NULL;
455 priv->in_reply_to = NULL;
456 priv->max_chars_banner = NULL;
458 if (!is_wp_text_buffer_started) {
459 is_wp_text_buffer_started = TRUE;
460 wp_text_buffer_library_init ();
465 hildon_program_add_window (hildon_program_get_instance(),
470 multimailbox_get_default_mailbox (const gchar *account_name)
472 gchar *transport_account;
473 gchar *result = NULL;
475 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
477 TNY_ACCOUNT_TYPE_TRANSPORT);
478 if (transport_account) {
480 ModestProtocolRegistry *registry;
482 registry = modest_runtime_get_protocol_registry ();
484 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
485 MODEST_ACCOUNT_PROTO, TRUE);
487 ModestProtocol *protocol =
488 modest_protocol_registry_get_protocol_by_name (registry,
489 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
491 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
492 ModestPairList *pair_list;
494 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
497 ModestPair *pair = (ModestPair *) pair_list->data;
498 result = g_strdup ((const gchar *) pair->first);
499 modest_pair_list_free (pair_list);
510 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
512 static ModestPairList*
513 get_transports (void)
515 GSList *transports = NULL;
517 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
518 GSList *accounts = modest_account_mgr_account_names (account_mgr,
519 TRUE /* only enabled accounts. */);
521 GSList *cursor = accounts;
523 gchar *account_name = cursor->data;
526 gchar *transport_account;
527 gboolean multi_mailbox = FALSE;
528 ModestProtocol *protocol = NULL;
530 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
532 transport_account = modest_account_mgr_get_server_account_name
533 (modest_runtime_get_account_mgr (),
535 TNY_ACCOUNT_TYPE_TRANSPORT);
536 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
537 ModestPairList *pair_list;
538 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
541 transports = g_slist_concat (transports, pair_list);
542 multi_mailbox = TRUE;
547 if (!multi_mailbox) {
548 gchar *from_string = NULL;
550 from_string = modest_account_mgr_get_from_string (account_mgr,
552 if (from_string && account_name) {
553 gchar *name = account_name;
554 ModestPair *pair = modest_pair_new ((gpointer) name,
555 (gpointer) from_string , TRUE);
556 transports = g_slist_prepend (transports, pair);
561 cursor = cursor->next;
563 g_slist_free (accounts); /* only free the accounts, not the elements,
564 * because they are used in the pairlist */
568 static void window_focus (GtkWindow *window,
572 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
576 scroll_drag_timeout (gpointer userdata)
578 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
579 ModestMsgEditWindowPrivate *priv;
581 /* It could happen that the window was already closed */
582 if (!GTK_WIDGET_VISIBLE (win))
585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
587 correct_scroll_without_drag_check (win, TRUE);
589 priv->scroll_drag_timeout_id = 0;
595 correct_scroll_without_drag_check_idle (gpointer userdata)
597 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
598 ModestMsgEditWindowPrivate *priv;
600 GdkRectangle rectangle;
601 gint offset_min, offset_max;
605 /* It could happen that the window was already closed */
606 if (!GTK_WIDGET_VISIBLE (w))
609 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
611 insert = gtk_text_buffer_get_insert (priv->text_buffer);
612 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
614 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
615 offset_min = priv->msg_body->allocation.y + rectangle.y;
616 offset_max = offset_min + rectangle.height;
618 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
619 offset_min = MAX (offset_min - 48, 0);
620 offset_max = MIN (offset_max + 48, vadj->upper);
622 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
624 priv->correct_scroll_idle = 0;
629 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
631 ModestMsgEditWindowPrivate *priv;
633 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
635 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
638 if (priv->correct_scroll_idle > 0) {
642 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
643 (GSourceFunc) correct_scroll_without_drag_check_idle,
649 correct_scroll (ModestMsgEditWindow *w)
651 ModestMsgEditWindowPrivate *priv;
653 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
654 if (gtk_grab_get_current () == priv->msg_body) {
655 if (priv->scroll_drag_timeout_id == 0) {
656 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
658 (GSourceFunc) scroll_drag_timeout,
665 correct_scroll_without_drag_check (w, TRUE);
669 text_buffer_end_user_action (GtkTextBuffer *buffer,
670 ModestMsgEditWindow *userdata)
673 correct_scroll (userdata);
677 text_buffer_mark_set (GtkTextBuffer *buffer,
680 ModestMsgEditWindow *userdata)
682 gtk_text_buffer_begin_user_action (buffer);
683 gtk_text_buffer_end_user_action (buffer);
687 cut_clipboard_check (GtkTextView *text_view,
690 GtkTextBuffer *buffer;
692 buffer = gtk_text_view_get_buffer (text_view);
693 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
694 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
699 copy_clipboard_check (GtkTextView *text_view,
702 GtkTextBuffer *buffer;
704 buffer = gtk_text_view_get_buffer (text_view);
705 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
706 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
711 attachment_deleted (ModestAttachmentsView *attachments_view,
714 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
719 connect_signals (ModestMsgEditWindow *obj)
721 ModestMsgEditWindowPrivate *priv;
723 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
725 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
726 G_CALLBACK (text_buffer_refresh_attributes), obj);
727 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
728 G_CALLBACK (text_buffer_can_undo), obj);
729 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
730 G_CALLBACK (text_buffer_can_redo), obj);
731 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
732 G_CALLBACK (body_changed), obj);
733 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
734 G_CALLBACK (body_insert_text), obj);
735 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
736 G_CALLBACK (body_changed), obj);
737 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
738 G_CALLBACK (text_buffer_end_user_action), obj);
739 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
740 G_CALLBACK (text_buffer_mark_set), obj);
741 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
742 G_CALLBACK (text_buffer_apply_tag), obj);
743 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
744 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
745 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
746 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
747 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
748 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
750 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
751 G_CALLBACK (modest_ui_actions_on_send), obj);
753 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
754 G_CALLBACK (from_field_changed), obj);
756 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
757 G_CALLBACK (msg_body_focus), obj);
758 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
759 G_CALLBACK (msg_body_focus), obj);
760 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
761 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
762 "changed", G_CALLBACK (recpt_field_changed), obj);
763 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
764 "changed", G_CALLBACK (recpt_field_changed), obj);
765 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
766 "changed", G_CALLBACK (recpt_field_changed), obj);
767 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
768 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
769 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
771 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
772 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
774 priv->clipboard_change_handler_id =
775 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
776 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
777 priv->default_clipboard_change_handler_id =
778 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
779 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
781 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
782 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
783 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
787 init_wp_text_view_style ()
789 static gboolean initialized = FALSE;
792 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
798 init_window (ModestMsgEditWindow *obj)
800 GtkWidget *to_caption, *subject_caption;
801 GtkWidget *main_vbox;
802 ModestMsgEditWindowPrivate *priv;
803 GtkActionGroup *action_group;
804 ModestWindowPrivate *parent_priv;
805 GdkPixbuf *window_icon = NULL;
806 GError *error = NULL;
808 GtkSizeGroup *title_size_group;
809 GtkSizeGroup *value_size_group;
810 GtkWidget *window_box;
811 GtkWidget *window_align;
812 #if (GTK_MINOR_VERSION >= 10)
813 GdkAtom deserialize_type;
815 GtkWidget *from_send_hbox;
816 GtkWidget *send_icon;
817 GtkWidget *attachments_label;
818 GtkWidget *branding_box;
820 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
821 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
823 parent_priv->ui_manager = gtk_ui_manager_new();
824 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
825 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
827 /* Add common actions */
828 gtk_action_group_add_actions (action_group,
829 modest_msg_edit_action_entries,
830 G_N_ELEMENTS (modest_msg_edit_action_entries),
832 gtk_action_group_add_actions (action_group,
833 hildon2_msg_edit_action_entries,
834 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
836 gtk_action_group_add_toggle_actions (action_group,
837 modest_msg_edit_toggle_action_entries,
838 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
840 gtk_action_group_add_radio_actions (action_group,
841 modest_msg_edit_alignment_radio_action_entries,
842 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
844 G_CALLBACK (modest_ui_actions_on_change_justify),
846 gtk_action_group_add_radio_actions (action_group,
847 modest_msg_edit_priority_action_entries,
848 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
850 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
852 gtk_action_group_add_radio_actions (action_group,
853 modest_msg_edit_file_format_action_entries,
854 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
855 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
856 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
858 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
859 g_object_unref (action_group);
861 /* Load the UI definition */
862 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
865 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
866 g_clear_error (&error);
869 /* Add accelerators */
870 gtk_window_add_accel_group (GTK_WINDOW (obj),
871 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
873 parent_priv->menubar = NULL;
875 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
876 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
878 /* Note: This ModestPairList* must exist for as long as the picker
879 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
880 * so it can't know how to manage its memory. */
881 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
882 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
884 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
885 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
886 _("mail_va_from"), priv->from_field);
887 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
888 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
889 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
891 priv->to_field = modest_recpt_editor_new ();
892 priv->cc_field = modest_recpt_editor_new ();
893 priv->bcc_field = modest_recpt_editor_new ();
894 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
895 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
896 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
897 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
898 priv->priority_icon = gtk_image_new ();
899 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
900 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
901 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
902 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
903 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
904 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
905 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
906 priv->attachments_view = modest_attachments_view_new (NULL);
907 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
908 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
910 priv->header_box = gtk_vbox_new (FALSE, 0);
912 to_caption = _create_addressbook_box
913 (title_size_group, value_size_group,
914 _("mail_va_to"), priv->to_field);
915 priv->cc_caption = _create_addressbook_box
916 (title_size_group, value_size_group,
917 _("mail_va_cc"), priv->cc_field);
918 priv->bcc_caption = _create_addressbook_box
919 (title_size_group, value_size_group,
920 _("mail_va_hotfix1"), priv->bcc_field);
921 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
922 _("mail_va_subject"), FALSE, priv->subject_box);
923 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
924 _("mail_va_attachment"),
926 priv->attachments_view,
927 HILDON_SIZE_AUTO_WIDTH |
928 HILDON_SIZE_AUTO_HEIGHT);
929 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
930 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
933 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
934 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
935 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
936 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
938 g_object_unref (title_size_group);
939 g_object_unref (value_size_group);
941 priv->brand_icon = gtk_image_new ();
942 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
943 priv->brand_label = gtk_label_new (NULL);
944 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
945 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
946 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
947 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
949 from_send_hbox = gtk_hbox_new (FALSE, 0);
950 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
951 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
953 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
954 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
955 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, TRUE, TRUE, 0);
958 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
959 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
960 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
961 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
962 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
963 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
964 gtk_box_pack_start (GTK_BOX (priv->header_box), branding_box, FALSE, FALSE, 0);
965 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
967 init_wp_text_view_style ();
969 priv->msg_body = modest_wp_text_view_new ();
972 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
973 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
974 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
975 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
976 #if (GTK_MINOR_VERSION >= 10)
977 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
978 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
980 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
981 deserialize_type, TRUE);
983 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
985 priv->find_toolbar = hildon_find_toolbar_new (NULL);
986 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
988 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
990 priv->pannable = hildon_pannable_area_new ();
992 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
994 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
995 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
996 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
998 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
999 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1000 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1002 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1003 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1005 window_box = gtk_vbox_new (FALSE, 0);
1006 gtk_container_add (GTK_CONTAINER(obj), window_box);
1008 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1010 /* Set window icon */
1011 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1013 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1014 g_object_unref (window_icon);
1019 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1021 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1023 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1024 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1025 priv->clipboard_change_handler_id))
1026 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1027 priv->clipboard_change_handler_id);
1028 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1029 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1030 priv->default_clipboard_change_handler_id))
1031 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1032 priv->default_clipboard_change_handler_id);
1034 if (priv->account_removed_handler_id &&
1035 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1036 priv->account_removed_handler_id))
1037 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1038 priv->account_removed_handler_id);
1042 modest_msg_edit_window_finalize (GObject *obj)
1044 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1046 if (priv->max_chars_banner) {
1047 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1048 priv->max_chars_banner = FALSE;
1051 /* Sanity check: shouldn't be needed, the window mgr should
1052 call this function before */
1053 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1055 if (priv->font_dialog != NULL) {
1056 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1059 if (priv->clipboard_text != NULL) {
1060 g_free (priv->clipboard_text);
1061 priv->clipboard_text = NULL;
1064 if (priv->draft_msg != NULL) {
1065 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1066 if (TNY_IS_HEADER (header)) {
1067 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1068 modest_window_mgr_unregister_header (mgr, header);
1070 g_object_unref (priv->draft_msg);
1071 priv->draft_msg = NULL;
1073 if (priv->outbox_msg != NULL) {
1074 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1075 if (TNY_IS_HEADER (header)) {
1076 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1077 modest_window_mgr_unregister_header (mgr, header);
1079 g_object_unref (priv->outbox_msg);
1080 priv->outbox_msg = NULL;
1082 if (priv->correct_scroll_idle > 0) {
1083 g_source_remove (priv->correct_scroll_idle);
1084 priv->correct_scroll_idle = 0;
1086 if (priv->scroll_drag_timeout_id > 0) {
1087 g_source_remove (priv->scroll_drag_timeout_id);
1088 priv->scroll_drag_timeout_id = 0;
1090 if (priv->clipboard_owner_idle > 0) {
1091 g_source_remove (priv->clipboard_owner_idle);
1092 priv->clipboard_owner_idle = 0;
1094 if (priv->original_account_name)
1095 g_free (priv->original_account_name);
1096 if (priv->original_mailbox)
1097 g_free (priv->original_mailbox);
1098 g_free (priv->msg_uid);
1099 g_free (priv->last_search);
1100 g_free (priv->references);
1101 g_free (priv->in_reply_to);
1102 g_object_unref (priv->attachments);
1103 g_object_unref (priv->images);
1105 /* This had to stay alive for as long as the picker that used it: */
1106 modest_pair_list_free (priv->from_field_protos);
1108 G_OBJECT_CLASS(parent_class)->finalize (obj);
1112 pixbuf_size_prepared (GdkPixbufLoader *loader,
1115 ModestMsgEditWindow *self)
1117 gint new_height, new_width;
1120 new_height = height;
1124 if (width > IMAGE_MAX_WIDTH) {
1125 new_height = height * IMAGE_MAX_WIDTH / width;
1126 new_width = IMAGE_MAX_WIDTH;
1129 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1133 pixbuf_from_stream (TnyStream *stream,
1134 const gchar *mime_type,
1135 guint64 *stream_size,
1136 ModestMsgEditWindow *self)
1138 GdkPixbufLoader *loader;
1141 GError *error = NULL;
1145 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1147 if (loader == NULL) {
1152 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1154 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1156 tny_stream_reset (TNY_STREAM (stream));
1157 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1158 unsigned char read_buffer[128];
1160 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1162 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1165 /* Allow some UI responsiveness */
1166 while (gtk_events_pending ())
1167 gtk_main_iteration ();
1169 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1171 gdk_pixbuf_loader_close (loader, &error);
1174 g_error_free (error);
1175 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1177 g_object_ref (pixbuf);
1178 g_object_unref (loader);
1183 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1184 GdkPixbuf *new_pixbuf;
1186 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1187 gdk_pixbuf_get_width (pixbuf);
1188 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1189 g_object_unref (pixbuf);
1190 pixbuf = new_pixbuf;
1194 *stream_size = size;
1200 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1202 ModestMsgEditWindowPrivate *priv;
1205 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1207 g_object_ref (self);
1208 for (iter = tny_list_create_iterator (attachments);
1209 !tny_iterator_is_done (iter);
1210 tny_iterator_next (iter)) {
1211 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1212 const gchar *cid = tny_mime_part_get_content_id (part);
1213 const gchar *mime_type = tny_mime_part_get_content_type (part);
1214 if ((cid != NULL)&&(mime_type != NULL)) {
1215 guint64 stream_size;
1216 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1217 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1220 g_object_unref (stream);
1222 if (pixbuf != NULL) {
1223 priv->images_count ++;
1224 priv->images_size += stream_size;
1225 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1226 g_object_unref (pixbuf);
1229 g_object_unref (part);
1231 g_object_unref (iter);
1232 g_object_unref (self);
1236 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1238 TnyMimePart *parent = NULL;
1239 const gchar *content_type = NULL;
1240 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1242 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1244 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1245 parent = g_object_ref (msg);
1246 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1247 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1250 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1251 iter = tny_list_create_iterator (parts);
1252 while (!tny_iterator_is_done (iter)) {
1254 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1255 content_type = tny_mime_part_get_content_type (part);
1256 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1260 g_object_unref (part);
1262 tny_iterator_next (iter);
1264 g_object_unref (iter);
1265 g_object_unref (parts);
1268 if (parent != NULL) {
1269 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1272 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1273 iter = tny_list_create_iterator (parts);
1274 while (!tny_iterator_is_done (iter)) {
1276 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1277 content_type = tny_mime_part_get_content_type (part);
1278 if (content_type && g_str_has_prefix (content_type, "image/")) {
1279 tny_list_prepend (priv->images, (GObject *) part);
1281 g_object_unref (part);
1282 tny_iterator_next (iter);
1284 g_object_unref (iter);
1285 g_object_unref (parts);
1286 g_object_unref (parent);
1291 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1294 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1296 for (iter = tny_list_create_iterator (attachments) ;
1297 !tny_iterator_is_done (iter);
1298 tny_iterator_next (iter)) {
1299 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1300 const gchar *cid = tny_mime_part_get_content_id (part);
1302 char *invalid = NULL;
1303 gint int_cid = strtol (cid, &invalid, 10);
1304 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1305 priv->next_cid = int_cid + 1;
1308 g_object_unref (part);
1310 g_object_unref (iter);
1314 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1317 gchar *to, *cc, *bcc, *subject;
1319 ModestMsgEditWindowPrivate *priv;
1320 ModestWindowPrivate *parent_priv;
1322 TnyHeaderFlags priority_flags;
1323 TnyFolder *msg_folder;
1324 gboolean is_html = FALSE;
1325 gboolean field_view_set;
1327 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1328 g_return_if_fail (TNY_IS_MSG (msg));
1330 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1331 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1333 header = tny_msg_get_header (msg);
1334 to = tny_header_dup_to (header);
1335 cc = tny_header_dup_cc (header);
1336 bcc = tny_header_dup_bcc (header);
1337 subject = tny_header_dup_subject (header);
1339 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1340 priority_flags = tny_header_get_priority (header);
1343 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1345 field_view_set = TRUE;
1347 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1348 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1349 gtk_widget_show (priv->cc_caption);
1350 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1351 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1352 gtk_widget_hide (priv->cc_caption);
1353 field_view_set = FALSE;
1355 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1357 field_view_set = TRUE;
1359 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1360 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1361 gtk_widget_show (priv->bcc_caption);
1362 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1363 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1364 gtk_widget_hide (priv->bcc_caption);
1365 field_view_set = FALSE;
1367 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1371 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1372 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1375 update_window_title (self);
1377 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1378 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1380 if ((body == NULL)||(body[0] == '\0')) {
1382 body = modest_text_utils_convert_to_html ("");
1385 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1386 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1389 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1392 /* Add attachments to the view */
1393 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1394 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1395 if (tny_list_get_length (priv->attachments) == 0) {
1396 gtk_widget_hide (priv->attachments_caption);
1398 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1399 gtk_widget_show_all (priv->attachments_caption);
1401 get_related_images (self, msg);
1402 update_next_cid (self, priv->attachments);
1403 update_next_cid (self, priv->images);
1404 replace_with_images (self, priv->images);
1406 if (preserve_is_rich && !is_html) {
1407 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1408 /* Get the default format required from configuration */
1409 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1410 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1413 /* Set the default focus depending on having already a To: field or not */
1414 if ((!to)||(*to == '\0')) {
1415 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1417 gtk_widget_grab_focus (priv->msg_body);
1420 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1422 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1423 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1425 modest_msg_edit_window_set_modified (self, FALSE);
1427 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1428 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1429 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1430 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1432 if (priv->msg_uid) {
1433 g_free (priv->msg_uid);
1434 priv->msg_uid = NULL;
1437 /* we should set a reference to the incoming message if it is a draft */
1438 msg_folder = tny_msg_get_folder (msg);
1440 if (modest_tny_folder_is_local_folder (msg_folder)) {
1441 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1442 if (type == TNY_FOLDER_TYPE_INVALID)
1443 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1445 if (type == TNY_FOLDER_TYPE_DRAFTS)
1446 priv->draft_msg = g_object_ref(msg);
1447 if (type == TNY_FOLDER_TYPE_OUTBOX)
1448 priv->outbox_msg = g_object_ref(msg);
1449 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1451 g_object_unref (msg_folder);
1462 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1464 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1465 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1466 GtkWidget *placeholder;
1467 GtkWidget *tool_item;
1472 GtkWidget *sizes_menu;
1473 GtkWidget *fonts_menu;
1479 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1480 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1481 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1482 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1484 /* Font color placeholder */
1485 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1486 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1489 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1490 priv->font_color_button = hildon_color_button_new ();
1491 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1492 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1493 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1494 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1495 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1496 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1497 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1498 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1500 G_CALLBACK (modest_msg_edit_window_color_button_change),
1503 /* Font size and face placeholder */
1504 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1505 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1507 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1508 priv->size_tool_button_label = gtk_label_new (NULL);
1509 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1510 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1511 size_text, "</span>", NULL);
1512 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1513 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1515 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1516 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1517 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1518 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1519 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1520 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1521 gtk_widget_set_sensitive (arrow, FALSE);
1522 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1523 sizes_menu = gtk_menu_new ();
1524 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1525 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1528 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1529 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1531 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1535 if (wp_font_size[size_index] == 12)
1536 priv->current_size_index = size_index;
1540 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1541 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1542 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1543 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1544 priv->font_size_toolitem = tool_item;
1547 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1548 priv->font_tool_button_label = gtk_label_new (NULL);
1549 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1550 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1551 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1553 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1554 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1555 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1556 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1557 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1558 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1559 gtk_widget_set_sensitive (arrow, FALSE);
1560 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1561 fonts_menu = gtk_menu_new ();
1562 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1563 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1566 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1568 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1569 0, wp_get_font_name (font_index),
1572 if (font_index == DEFAULT_FONT)
1573 priv->current_face_index = font_index;
1575 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1576 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1577 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1578 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1579 priv->font_face_toolitem = tool_item;
1581 /* Set expand and homogeneous for remaining items */
1582 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1583 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1584 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1585 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1586 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1587 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1589 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1590 will not show the tool items added to the placeholders) */
1591 gtk_widget_show_all (parent_priv->toolbar);
1593 /* Set the no show all *after* showing all items. We do not
1594 want the toolbar to be shown with a show all because it
1595 could go agains the gconf setting regarding showing or not
1596 the toolbar of the editor window */
1597 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1603 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1606 ModestWindowPrivate *parent_priv;
1607 ModestMsgEditWindowPrivate *priv;
1608 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1609 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1610 ModestWindowMgr *mgr = NULL;
1612 g_return_val_if_fail (msg, NULL);
1613 g_return_val_if_fail (account_name, NULL);
1615 mgr = modest_runtime_get_window_mgr ();
1617 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1619 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1620 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1622 /* Menubar. Update the state of some toggles */
1623 priv->from_field_protos = get_transports ();
1624 priv->original_mailbox = NULL;
1625 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1626 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1627 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1628 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1629 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1630 priv->original_mailbox = g_strdup (mailbox);
1631 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1632 /* We set the first mailbox as the active mailbox */
1633 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1634 if (priv->original_mailbox != NULL)
1635 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1636 (gpointer) priv->original_mailbox);
1638 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1639 (gpointer) account_name);
1641 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1643 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1644 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1645 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1647 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1648 hildon_touch_selector_get_current_text
1649 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1650 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1651 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1654 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1656 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1658 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1659 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1661 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1663 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1664 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1665 /* Add common dimming rules */
1666 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1667 modest_msg_edit_window_toolbar_dimming_entries,
1668 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1669 MODEST_WINDOW (obj));
1670 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1671 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1672 MODEST_WINDOW (obj));
1673 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1674 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1675 MODEST_WINDOW (obj));
1676 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1677 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1678 MODEST_WINDOW (obj));
1679 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1680 G_CALLBACK (modest_ui_dimming_rules_on_send),
1681 MODEST_WINDOW (obj));
1682 /* Insert dimming rules group for this window */
1683 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1684 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1686 /* Setup app menu */
1687 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1689 /* Checks the dimming rules */
1690 g_object_unref (toolbar_rules_group);
1691 g_object_unref (clipboard_rules_group);
1692 gtk_widget_hide (priv->priority_icon);
1693 gtk_widget_queue_resize (priv->subject_box);
1694 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1696 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1698 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1699 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1700 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1701 priv->update_caption_visibility = TRUE;
1703 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1705 /* Track account-removed signal, this window should be closed
1706 in the case we're creating a mail associated to the account
1708 priv->account_removed_handler_id =
1709 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1711 G_CALLBACK(on_account_removed),
1714 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1716 return (ModestWindow*) obj;
1720 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1722 GString **string_buffer = (GString **) user_data;
1724 *string_buffer = g_string_append (*string_buffer, buffer);
1730 * @result: A new string which should be freed with g_free().
1733 get_formatted_data (ModestMsgEditWindow *edit_window)
1735 ModestMsgEditWindowPrivate *priv;
1736 GString *string_buffer = g_string_new ("");
1738 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1740 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1742 modest_text_utils_hyperlinkify (string_buffer);
1744 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1746 return g_string_free (string_buffer, FALSE);
1751 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1754 const gchar *account_name;
1755 ModestMsgEditWindowPrivate *priv;
1756 TnyIterator *att_iter;
1757 const gchar *picker_active_id;
1759 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1761 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1763 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1764 g_return_val_if_fail (picker_active_id, NULL);
1765 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1767 /* don't free these (except from) */
1768 data = g_slice_new0 (MsgData);
1769 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1770 data->account_name = g_strdup (account_name);
1771 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1772 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1773 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1774 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1775 data->references = g_strdup (priv->references);
1776 data->in_reply_to = g_strdup (priv->in_reply_to);
1777 if (priv->draft_msg) {
1778 data->draft_msg = g_object_ref (priv->draft_msg);
1779 } else if (priv->outbox_msg) {
1780 data->draft_msg = g_object_ref (priv->outbox_msg);
1782 data->draft_msg = NULL;
1785 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1787 gtk_text_buffer_get_bounds (buf, &b, &e);
1788 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1790 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1791 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1793 data->html_body = NULL;
1795 /* deep-copy the data */
1796 att_iter = tny_list_create_iterator (priv->attachments);
1797 data->attachments = NULL;
1798 while (!tny_iterator_is_done (att_iter)) {
1799 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1800 if (!(TNY_IS_MIME_PART(part))) {
1801 g_warning ("strange data in attachment list");
1802 g_object_unref (part);
1803 tny_iterator_next (att_iter);
1806 data->attachments = g_list_append (data->attachments,
1808 tny_iterator_next (att_iter);
1810 g_object_unref (att_iter);
1812 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1813 att_iter = tny_list_create_iterator (priv->images);
1814 data->images = NULL;
1815 while (!tny_iterator_is_done (att_iter)) {
1816 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1818 if (!(TNY_IS_MIME_PART(part))) {
1819 g_warning ("strange data in attachment list");
1820 g_object_unref (part);
1821 tny_iterator_next (att_iter);
1824 cid = tny_mime_part_get_content_id (part);
1826 gchar *image_tag_id;
1827 GtkTextTag *image_tag;
1829 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1830 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1831 g_free (image_tag_id);
1833 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1835 ((gtk_text_iter_has_tag (&iter, image_tag))||
1836 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1837 data->images = g_list_append (data->images,
1838 g_object_ref (part));
1840 g_object_unref (part);
1841 tny_iterator_next (att_iter);
1843 g_object_unref (att_iter);
1845 data->priority_flags = priv->priority_flags;
1852 unref_gobject (GObject *obj, gpointer data)
1854 if (!G_IS_OBJECT(obj))
1856 g_object_unref (obj);
1860 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1863 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1871 g_free (data->from);
1872 g_free (data->subject);
1873 g_free (data->plain_body);
1874 g_free (data->html_body);
1875 g_free (data->account_name);
1876 g_free (data->references);
1877 g_free (data->in_reply_to);
1879 if (data->draft_msg != NULL) {
1880 g_object_unref (data->draft_msg);
1881 data->draft_msg = NULL;
1884 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1885 g_list_free (data->attachments);
1886 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1887 g_list_free (data->images);
1889 g_slice_free (MsgData, data);
1893 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1895 guint64 *parts_size)
1897 ModestMsgEditWindowPrivate *priv;
1899 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1901 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1903 /* TODO: add images */
1904 *parts_size += priv->images_size;
1905 *parts_count += priv->images_count;
1910 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1913 ModestMsgEditWindowPrivate *priv = NULL;
1914 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1916 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1918 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1920 return MODEST_MSG_EDIT_FORMAT_HTML;
1922 return MODEST_MSG_EDIT_FORMAT_TEXT;
1926 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1927 ModestMsgEditFormat format)
1929 ModestMsgEditWindowPrivate *priv;
1930 ModestWindowPrivate *parent_priv;
1932 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1933 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1934 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1937 case MODEST_MSG_EDIT_FORMAT_HTML:
1938 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1939 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1941 case MODEST_MSG_EDIT_FORMAT_TEXT:
1942 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1943 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1946 g_return_if_reached ();
1950 ModestMsgEditFormatState *
1951 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1953 ModestMsgEditFormatState *format_state = NULL;
1954 ModestMsgEditWindowPrivate *priv;
1955 WPTextBufferFormat *buffer_format;
1957 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1959 buffer_format = g_new0 (WPTextBufferFormat, 1);
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1962 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1964 format_state = g_new0 (ModestMsgEditFormatState, 1);
1965 format_state->bold = buffer_format->bold&0x1;
1966 format_state->italics = buffer_format->italic&0x1;
1967 format_state->bullet = buffer_format->bullet&0x1;
1968 format_state->color = buffer_format->color;
1969 format_state->font_size = buffer_format->font_size;
1970 format_state->font_family = wp_get_font_name (buffer_format->font);
1971 format_state->justification = buffer_format->justification;
1972 g_free (buffer_format);
1974 return format_state;
1979 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1980 const ModestMsgEditFormatState *format_state)
1982 ModestMsgEditWindowPrivate *priv;
1983 WPTextBufferFormat *buffer_format;
1984 WPTextBufferFormat *current_format;
1986 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1987 g_return_if_fail (format_state != NULL);
1989 buffer_format = g_new0 (WPTextBufferFormat, 1);
1990 current_format = g_new0 (WPTextBufferFormat, 1);
1992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1993 gtk_widget_grab_focus (priv->msg_body);
1994 buffer_format->bold = (format_state->bold != FALSE);
1995 buffer_format->italic = (format_state->italics != FALSE);
1996 buffer_format->color = format_state->color;
1997 buffer_format->font_size = format_state->font_size;
1998 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1999 buffer_format->justification = format_state->justification;
2000 buffer_format->bullet = format_state->bullet;
2002 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2004 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2005 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2006 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2007 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2008 buffer_format->cs.font = (buffer_format->font != current_format->font);
2009 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2010 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2012 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2013 if (buffer_format->cs.bold) {
2014 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2015 GINT_TO_POINTER (buffer_format->bold&0x1));
2017 if (buffer_format->cs.italic) {
2018 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2019 GINT_TO_POINTER (buffer_format->italic&0x1));
2021 if (buffer_format->cs.color) {
2022 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2023 GINT_TO_POINTER (&(buffer_format->color)));
2025 if (buffer_format->cs.font_size) {
2026 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2027 GINT_TO_POINTER (buffer_format->font_size));
2029 if (buffer_format->cs.justification) {
2030 switch (buffer_format->justification) {
2031 case GTK_JUSTIFY_LEFT:
2032 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2033 GINT_TO_POINTER(TRUE));
2035 case GTK_JUSTIFY_CENTER:
2036 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2037 GINT_TO_POINTER(TRUE));
2039 case GTK_JUSTIFY_RIGHT:
2040 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2041 GINT_TO_POINTER(TRUE));
2048 if (buffer_format->cs.font) {
2049 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2050 GINT_TO_POINTER (buffer_format->font));
2052 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2053 if (buffer_format->cs.bullet) {
2054 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2055 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2057 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2059 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2061 g_free (buffer_format);
2062 g_free (current_format);
2064 /* Check dimming rules */
2065 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2066 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2070 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2072 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2074 ModestWindowPrivate *parent_priv;
2075 ModestMsgEditWindowPrivate *priv;
2077 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2078 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2080 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2081 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2082 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2083 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2085 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2086 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2087 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2090 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2092 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2093 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2095 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2096 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2098 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2099 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2102 switch (buffer_format->justification)
2104 case GTK_JUSTIFY_LEFT:
2105 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2107 case GTK_JUSTIFY_CENTER:
2108 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2110 case GTK_JUSTIFY_RIGHT:
2111 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2118 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2120 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2121 G_CALLBACK (modest_msg_edit_window_color_button_change),
2123 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2124 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2125 G_CALLBACK (modest_msg_edit_window_color_button_change),
2128 if (priv->current_size_index != buffer_format->font_size) {
2132 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2133 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2137 priv->current_size_index = buffer_format->font_size;
2139 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2140 markup = g_strconcat ("<span font_family='Sans'>",
2141 size_text, "</span>", NULL);
2143 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2147 gtk_tree_path_free (path);
2150 if (priv->current_face_index != buffer_format->font) {
2154 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2155 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2159 priv->current_face_index = buffer_format->font;
2160 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2161 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2162 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2169 g_free (buffer_format);
2173 #ifdef MODEST_HILDON_VERSION_0
2175 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2178 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2179 ModestMsgEditWindowPrivate *priv;
2180 GtkWidget *dialog = NULL;
2182 GdkColor *new_color = NULL;
2184 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2185 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2187 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2188 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2189 g_free (buffer_format);
2191 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2192 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2193 if (new_color != NULL) {
2194 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2195 (gpointer) new_color);
2198 gtk_widget_destroy (dialog);
2203 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2206 ModestMsgEditWindowPrivate *priv;
2207 GtkWidget *dialog = NULL;
2209 GdkColor *old_color = NULL;
2210 const GdkColor *new_color = NULL;
2212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2213 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2215 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2216 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2218 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2219 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2220 if (new_color != NULL)
2221 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2223 gtk_widget_destroy (dialog);
2229 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2232 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2233 ModestMsgEditWindowPrivate *priv;
2234 GtkWidget *dialog = NULL;
2236 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2237 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2239 dialog = hildon_color_chooser_new ();
2240 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2241 g_free (buffer_format);
2243 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2245 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2246 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2249 gtk_widget_destroy (dialog);
2254 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2257 ModestMsgEditWindowPrivate *priv;
2258 GtkWidget *dialog = NULL;
2259 GdkColor *old_color = NULL;
2261 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2262 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2264 dialog = hildon_color_chooser_new ();
2265 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2267 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2269 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2270 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2272 gtk_widget_destroy (dialog);
2275 #endif /*!MODEST_HILDON_VERSION_0*/
2280 create_stream_for_uri (const gchar* uri)
2285 TnyStream *result = NULL;
2287 GnomeVFSHandle *handle = NULL;
2288 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2289 if (test == GNOME_VFS_OK) {
2290 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2291 /* Streams over OBEX (Bluetooth) are not seekable but
2292 * we expect them to be (we might need to read them
2293 * several times). So if this is a Bluetooth URI just
2294 * read the whole file into memory (this is not a fast
2295 * protocol so we can assume that these files are not
2296 * going to be very big) */
2297 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2298 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2299 TnyStream *memstream = tny_camel_mem_stream_new ();
2300 tny_stream_write_to_stream (vfssstream, memstream);
2301 g_object_unref (vfssstream);
2304 result = vfssstream;
2312 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2315 ModestMsgEditWindowPrivate *priv;
2316 GtkWidget *dialog = NULL;
2318 GSList *uris = NULL;
2319 GSList *uri_node = NULL;
2321 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2323 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2324 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2325 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2327 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2329 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2330 GTK_WINDOW (dialog), GTK_WINDOW (window));
2332 response = gtk_dialog_run (GTK_DIALOG (dialog));
2334 case GTK_RESPONSE_OK:
2336 gchar *current_folder;
2337 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2338 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2339 if (current_folder && current_folder != '\0') {
2341 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2342 current_folder, &err);
2344 g_debug ("Error storing latest used folder: %s", err->message);
2348 g_free (current_folder);
2354 gtk_widget_destroy (dialog);
2356 g_object_ref (window);
2357 /* The operation could take some time so allow the dialog to be closed */
2358 while (gtk_events_pending ())
2359 gtk_main_iteration ();
2361 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2363 GnomeVFSHandle *handle = NULL;
2364 GnomeVFSResult result;
2365 GtkTextIter position;
2366 GtkTextMark *insert_mark;
2368 uri = (const gchar *) uri_node->data;
2369 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2370 if (result == GNOME_VFS_OK) {
2372 GnomeVFSFileInfo *info;
2373 gchar *filename, *basename, *escaped_filename;
2374 TnyMimePart *mime_part;
2376 const gchar *mime_type = NULL;
2377 GnomeVFSURI *vfs_uri;
2378 guint64 stream_size;
2380 gnome_vfs_close (handle);
2381 vfs_uri = gnome_vfs_uri_new (uri);
2383 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2384 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2385 g_free (escaped_filename);
2386 gnome_vfs_uri_unref (vfs_uri);
2387 info = gnome_vfs_file_info_new ();
2389 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2390 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2392 mime_type = gnome_vfs_file_info_get_mime_type (info);
2394 mime_part = tny_platform_factory_new_mime_part
2395 (modest_runtime_get_platform_factory ());
2397 TnyStream *stream = create_stream_for_uri (uri);
2399 if (stream == NULL) {
2401 modest_platform_information_banner (NULL, NULL,
2402 _FM("sfil_ib_opening_not_allowed"));
2404 g_object_unref (mime_part);
2405 gnome_vfs_file_info_unref (info);
2409 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2411 content_id = g_strdup_printf ("%d", priv->next_cid);
2412 tny_mime_part_set_content_id (mime_part, content_id);
2413 g_free (content_id);
2416 basename = g_path_get_basename (filename);
2417 tny_mime_part_set_filename (mime_part, basename);
2420 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2422 if (pixbuf != NULL) {
2423 priv->images_size += stream_size;
2424 priv->images_count ++;
2425 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2426 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2427 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2428 tny_mime_part_get_content_id (mime_part), pixbuf);
2429 g_object_unref (pixbuf);
2431 tny_list_prepend (priv->images, (GObject *) mime_part);
2432 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2434 modest_platform_information_banner (NULL, NULL,
2435 _("mail_ib_file_operation_failed"));
2439 g_object_unref (mime_part);
2440 gnome_vfs_file_info_unref (info);
2444 g_object_unref (window);
2448 on_attach_file_response (GtkDialog *dialog,
2452 GSList *uris = NULL;
2454 GnomeVFSFileSize total_size, allowed_size;
2455 ModestMsgEditWindow *window;
2456 ModestMsgEditWindowPrivate *priv;
2461 case GTK_RESPONSE_OK:
2463 gchar *current_folder;
2465 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2466 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2467 if (current_folder && current_folder != '\0') {
2469 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2470 current_folder, &err);
2472 g_debug ("Error storing latest used folder: %s", err->message);
2476 g_free (current_folder);
2483 window = MODEST_MSG_EDIT_WINDOW (user_data);
2484 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2486 /* allowed size is the maximum size - what's already there */
2487 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2488 &att_num, &att_size);
2489 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2492 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2494 const gchar *uri = (const gchar *) uri_node->data;
2497 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2499 if (total_size > allowed_size) {
2500 g_debug ("%s: total size: %u",
2501 __FUNCTION__, (unsigned int)total_size);
2504 allowed_size -= total_size;
2506 g_slist_foreach (uris, (GFunc) g_free, NULL);
2507 g_slist_free (uris);
2509 gtk_widget_destroy (GTK_WIDGET (dialog));
2513 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2515 GtkWidget *dialog = NULL;
2516 ModestMsgEditWindowPrivate *priv;
2519 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2521 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2523 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2526 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2527 GTK_FILE_CHOOSER_ACTION_OPEN);
2528 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2529 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2530 if (conf_folder && conf_folder[0] != '\0') {
2531 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2534 /* Set the default folder to images folder */
2535 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2536 ".documents", NULL);
2537 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2538 g_free (docs_folder);
2540 g_free (conf_folder);
2541 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2542 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2543 GTK_WINDOW (dialog), GTK_WINDOW (window));
2545 /* Connect to response & show */
2546 g_signal_connect (dialog, "response",
2547 G_CALLBACK (on_attach_file_response), window);
2548 gtk_widget_show (dialog);
2553 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2555 GnomeVFSFileSize allowed_size)
2558 GnomeVFSHandle *handle = NULL;
2559 ModestMsgEditWindowPrivate *priv;
2560 GnomeVFSResult result;
2561 GnomeVFSFileSize size = 0;
2562 g_return_val_if_fail (window, 0);
2563 g_return_val_if_fail (uri, 0);
2565 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2567 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2568 if (result == GNOME_VFS_OK) {
2569 TnyMimePart *mime_part;
2571 const gchar *mime_type = NULL;
2573 gchar *escaped_filename;
2576 GnomeVFSFileInfo *info;
2577 GnomeVFSURI *vfs_uri;
2579 gnome_vfs_close (handle);
2580 vfs_uri = gnome_vfs_uri_new (uri);
2583 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2584 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2585 g_free (escaped_filename);
2586 gnome_vfs_uri_unref (vfs_uri);
2588 info = gnome_vfs_file_info_new ();
2590 if (gnome_vfs_get_file_info (uri,
2592 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2594 mime_type = gnome_vfs_file_info_get_mime_type (info);
2595 mime_part = tny_platform_factory_new_mime_part
2596 (modest_runtime_get_platform_factory ());
2598 /* try to get the attachment's size; this may fail for weird
2599 * file systems, like obex, upnp... */
2600 if (allowed_size != 0 &&
2601 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2603 if (size > allowed_size) {
2604 modest_platform_information_banner (NULL, NULL,
2605 _("mail_ib_error_attachment_size"));
2610 g_debug ("%s: could not get attachment size", __FUNCTION__);
2612 stream = create_stream_for_uri (uri);
2614 if (stream == NULL) {
2616 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2618 g_object_unref (mime_part);
2620 gnome_vfs_file_info_unref (info);
2624 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2625 g_object_unref (stream);
2627 content_id = g_strdup_printf ("%d", priv->next_cid);
2628 tny_mime_part_set_content_id (mime_part, content_id);
2629 g_free (content_id);
2632 basename = g_path_get_basename (filename);
2633 tny_mime_part_set_filename (mime_part, basename);
2636 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2637 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2639 info->size == 0, info->size);
2640 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2641 gtk_widget_show_all (priv->attachments_caption);
2642 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2644 g_object_unref (mime_part);
2645 gnome_vfs_file_info_unref (info);
2652 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2655 ModestMsgEditWindowPrivate *priv;
2658 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2659 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2661 if (att_list == NULL) {
2662 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2663 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2664 g_object_unref (att_list);
2668 g_object_ref (att_list);
2671 if (tny_list_get_length (att_list) == 0) {
2672 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2674 gboolean dialog_response;
2675 gchar *message = NULL;
2676 gchar *filename = NULL;
2678 if (tny_list_get_length (att_list) == 1) {
2680 iter = tny_list_create_iterator (att_list);
2681 part = (TnyMimePart *) tny_iterator_get_current (iter);
2682 g_object_unref (iter);
2683 if (TNY_IS_MSG (part)) {
2684 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2686 filename = tny_header_dup_subject (header);
2687 g_object_unref (header);
2689 if (filename == NULL) {
2690 filename = g_strdup (_("mail_va_no_subject"));
2693 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2695 g_object_unref (part);
2697 filename = g_strdup ("");
2699 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2700 "emev_nc_delete_attachments",
2701 tny_list_get_length (att_list)), filename);
2704 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2708 if (dialog_response != GTK_RESPONSE_OK) {
2709 g_object_unref (att_list);
2713 for (iter = tny_list_create_iterator (att_list);
2714 !tny_iterator_is_done (iter);
2715 tny_iterator_next (iter)) {
2716 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2717 const gchar *att_id;
2718 tny_list_remove (priv->attachments, (GObject *) mime_part);
2720 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2722 if (tny_list_get_length (priv->attachments) == 0)
2723 gtk_widget_hide (priv->attachments_caption);
2724 att_id = tny_mime_part_get_content_id (mime_part);
2726 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2728 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2729 g_object_unref (mime_part);
2731 g_object_unref (iter);
2734 g_object_unref (att_list);
2736 /* if the last attachment has been removed, focus the Subject: field */
2737 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2738 gtk_widget_grab_focus (priv->subject_field);
2742 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2745 ModestMsgEditWindowPrivate *priv;
2746 GdkColor *new_color;
2747 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2749 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2750 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2753 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2755 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2757 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2759 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2764 font_size_clicked (GtkToolButton *button,
2765 ModestMsgEditWindow *window)
2767 ModestMsgEditWindowPrivate *priv;
2768 GtkWidget *selector, *dialog;
2770 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2772 selector = hildon_touch_selector_new ();
2773 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2774 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2776 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2777 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2778 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2780 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2784 WPTextBufferFormat format;
2786 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2788 memset (&format, 0, sizeof (format));
2789 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2791 format.cs.font_size = TRUE;
2792 format.cs.text_position = TRUE;
2793 format.cs.font = TRUE;
2794 format.font_size = new_index;
2795 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2797 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2798 GINT_TO_POINTER (new_index)))
2799 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2801 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2802 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2803 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2804 size_text, "</span>", NULL);
2806 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2810 gtk_widget_destroy (dialog);
2812 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2817 font_face_clicked (GtkToolButton *button,
2818 ModestMsgEditWindow *window)
2820 ModestMsgEditWindowPrivate *priv;
2821 GtkWidget *selector, *dialog;
2822 GtkCellRenderer *renderer;
2824 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2826 selector = hildon_touch_selector_new ();
2827 renderer = gtk_cell_renderer_text_new ();
2828 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2829 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2830 renderer, "family", 0, "text", 0, NULL);
2831 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2833 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2834 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2835 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2837 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2838 gint new_font_index;
2842 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2843 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2844 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2848 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2850 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2851 GINT_TO_POINTER(new_font_index)))
2852 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2854 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2855 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2857 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2861 gtk_tree_path_free (path);
2864 gtk_widget_destroy (dialog);
2866 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2871 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2874 ModestMsgEditWindowPrivate *priv = NULL;
2875 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2877 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2878 if (!priv->update_caption_visibility)
2881 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2883 gtk_widget_show (priv->cc_caption);
2885 gtk_widget_hide (priv->cc_caption);
2887 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2891 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2894 ModestMsgEditWindowPrivate *priv = NULL;
2895 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2897 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2898 if (!priv->update_caption_visibility)
2901 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2903 gtk_widget_show (priv->bcc_caption);
2905 gtk_widget_hide (priv->bcc_caption);
2907 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2911 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2912 ModestRecptEditor *editor)
2914 ModestMsgEditWindowPrivate *priv;
2916 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2917 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2919 /* we check for low-mem; in that case, show a warning, and don't allow
2920 * for the addressbook
2922 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2925 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2927 if (editor == NULL) {
2928 GtkWidget *view_focus, *parent;
2929 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2931 /* This code should be kept in sync with ModestRecptEditor. The
2932 textview inside the recpt editor is the one that really gets the
2933 focus. As it's inside a scrolled window, and this one inside the
2934 hbox recpt editor inherits from, we'll need to go up in the
2935 hierarchy to know if the text view is part of the recpt editor
2936 or if it's a different text entry */
2937 parent = gtk_widget_get_parent (view_focus);
2938 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2939 editor = MODEST_RECPT_EDITOR (parent);
2942 editor = MODEST_RECPT_EDITOR (priv->to_field);
2945 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2949 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2951 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2953 modest_msg_edit_window_open_addressbook (window, NULL);
2957 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2958 gboolean show_toolbar)
2960 ModestWindowPrivate *parent_priv;
2961 ModestMsgEditWindowPrivate *priv;
2963 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2964 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2965 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2967 /* We can not just use the code of
2968 modest_msg_edit_window_setup_toolbar because it has a
2969 mixture of both initialization and creation code. */
2971 gint current_format;
2972 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2973 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2974 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2975 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2977 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2980 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2985 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2986 TnyHeaderFlags priority_flags)
2988 ModestMsgEditWindowPrivate *priv;
2989 ModestWindowPrivate *parent_priv;
2991 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2994 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2996 if (priv->priority_flags != priority_flags) {
2997 GtkAction *priority_action = NULL;
2999 priv->priority_flags = priority_flags;
3001 switch (priority_flags) {
3002 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3003 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3004 MODEST_HEADER_ICON_HIGH,
3005 HILDON_ICON_SIZE_SMALL);
3006 gtk_widget_show (priv->priority_icon);
3007 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3008 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3010 case TNY_HEADER_FLAG_LOW_PRIORITY:
3011 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3012 MODEST_HEADER_ICON_LOW,
3013 HILDON_ICON_SIZE_SMALL);
3014 gtk_widget_show (priv->priority_icon);
3015 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3016 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3019 gtk_widget_hide (priv->priority_icon);
3020 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3021 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3024 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3025 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3027 gtk_widget_queue_resize (priv->subject_box);
3031 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3034 ModestMsgEditWindowPrivate *priv;
3035 ModestWindowPrivate *parent_priv;
3036 gint current_format;
3038 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3040 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3043 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3044 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3046 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3048 if (parent_priv->toolbar) {
3049 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3050 gtk_widget_hide (parent_priv->toolbar);
3052 gtk_widget_show (parent_priv->toolbar);
3056 if (current_format != file_format) {
3057 switch (file_format) {
3058 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3059 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3060 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3062 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3066 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3067 response = gtk_dialog_run (GTK_DIALOG (dialog));
3068 gtk_widget_destroy (dialog);
3069 if (response == GTK_RESPONSE_OK) {
3070 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3071 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3073 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3074 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3079 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3080 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3081 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3086 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3089 ModestMsgEditWindowPrivate *priv;
3090 WPTextBufferFormat oldfmt, fmt;
3091 gint old_position = 0;
3095 GdkColor *color = NULL;
3096 gboolean bold, bold_set, italic, italic_set;
3097 gboolean underline, underline_set;
3098 gboolean strikethrough, strikethrough_set;
3099 gboolean position_set;
3100 gboolean font_size_set, font_set, color_set;
3103 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3104 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3106 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3107 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3108 GTK_WINDOW(dialog), GTK_WINDOW (window));
3110 /* First we get the currently selected font information */
3111 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3113 switch (oldfmt.text_position) {
3114 case TEXT_POSITION_NORMAL:
3117 case TEXT_POSITION_SUPERSCRIPT:
3125 g_object_set (G_OBJECT (dialog),
3126 "bold", oldfmt.bold != FALSE,
3127 "bold-set", !oldfmt.cs.bold,
3128 "underline", oldfmt.underline != FALSE,
3129 "underline-set", !oldfmt.cs.underline,
3130 "italic", oldfmt.italic != FALSE,
3131 "italic-set", !oldfmt.cs.italic,
3132 "strikethrough", oldfmt.strikethrough != FALSE,
3133 "strikethrough-set", !oldfmt.cs.strikethrough,
3134 "color", &oldfmt.color,
3135 "color-set", !oldfmt.cs.color,
3136 "size", wp_font_size[oldfmt.font_size],
3137 "size-set", !oldfmt.cs.font_size,
3138 "position", old_position,
3139 "position-set", !oldfmt.cs.text_position,
3140 "family", wp_get_font_name (oldfmt.font),
3141 "family-set", !oldfmt.cs.font,
3144 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3145 GTK_WINDOW (dialog), GTK_WINDOW (window));
3146 gtk_widget_show_all (dialog);
3147 priv->font_dialog = dialog;
3148 response = gtk_dialog_run (GTK_DIALOG (dialog));
3149 priv->font_dialog = NULL;
3150 if (response == GTK_RESPONSE_OK) {
3152 g_object_get( dialog,
3154 "bold-set", &bold_set,
3155 "underline", &underline,
3156 "underline-set", &underline_set,
3158 "italic-set", &italic_set,
3159 "strikethrough", &strikethrough,
3160 "strikethrough-set", &strikethrough_set,
3162 "color-set", &color_set,
3164 "size-set", &font_size_set,
3165 "family", &font_name,
3166 "family-set", &font_set,
3167 "position", &position,
3168 "position-set", &position_set,
3173 if (response == GTK_RESPONSE_OK) {
3174 memset(&fmt, 0, sizeof(fmt));
3180 fmt.italic = italic;
3181 fmt.cs.italic = TRUE;
3183 if (underline_set) {
3184 fmt.underline = underline;
3185 fmt.cs.underline = TRUE;
3187 if (strikethrough_set) {
3188 fmt.strikethrough = strikethrough;
3189 fmt.cs.strikethrough = TRUE;
3194 ? TEXT_POSITION_NORMAL
3195 : ( ( position == 1 )
3196 ? TEXT_POSITION_SUPERSCRIPT
3197 : TEXT_POSITION_SUBSCRIPT );
3198 fmt.cs.text_position = TRUE;
3199 fmt.font_size = oldfmt.font_size;
3203 fmt.cs.color = TRUE;
3206 fmt.font = wp_get_font_index(font_name,
3211 if (font_size_set) {
3212 fmt.cs.font_size = TRUE;
3213 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3215 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3216 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3218 gtk_widget_destroy (dialog);
3220 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3224 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3226 ModestMsgEditWindowPrivate *priv;
3228 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3229 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3231 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3233 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3234 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3238 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3240 ModestMsgEditWindowPrivate *priv;
3242 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3243 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3245 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3247 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3248 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3253 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3255 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3257 priv->can_undo = can_undo;
3261 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3263 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3265 priv->can_redo = can_redo;
3269 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3271 ModestMsgEditWindowPrivate *priv;
3272 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3273 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3275 return priv->can_undo;
3279 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3281 ModestMsgEditWindowPrivate *priv;
3282 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3283 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3285 return priv->can_redo;
3290 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3293 GtkTextIter match_start, match_end;
3295 if (image_id == NULL)
3298 gtk_text_buffer_get_start_iter (buffer, &iter);
3300 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3301 GSList *tags = gtk_text_iter_get_tags (&match_start);
3303 for (node = tags; node != NULL; node = g_slist_next (node)) {
3304 GtkTextTag *tag = (GtkTextTag *) node->data;
3305 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3306 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3307 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3309 offset = gtk_text_iter_get_offset (&match_start);
3310 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3311 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3315 gtk_text_iter_forward_char (&iter);
3320 message_is_empty (ModestMsgEditWindow *window)
3322 ModestMsgEditWindowPrivate *priv = NULL;
3324 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3325 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3327 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3328 * so we can ignore markup.
3330 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3333 count = gtk_text_buffer_get_char_count (buf);
3339 msg_body_focus (GtkWidget *focus,
3340 GdkEventFocus *event,
3344 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3345 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3346 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3351 recpt_field_changed (GtkTextBuffer *buffer,
3352 ModestMsgEditWindow *editor)
3354 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3355 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3359 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3361 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3362 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3366 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3369 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3370 GtkTextBuffer *buffer;
3372 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3373 gtk_text_buffer_set_modified (buffer, modified);
3374 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3375 gtk_text_buffer_set_modified (buffer, modified);
3376 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3377 gtk_text_buffer_set_modified (buffer, modified);
3378 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3382 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3384 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3385 const char *account_name;
3386 GtkTextBuffer *buffer;
3388 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3389 if (gtk_text_buffer_get_modified (buffer))
3391 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3392 if (gtk_text_buffer_get_modified (buffer))
3394 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3395 if (gtk_text_buffer_get_modified (buffer))
3397 if (gtk_text_buffer_get_modified (priv->text_buffer))
3400 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3401 if (priv->original_mailbox) {
3402 if (!account_name || strcmp (account_name, priv->original_mailbox))
3404 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3415 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3417 ModestMsgEditWindowPrivate *priv = NULL;
3419 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3420 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3422 /* check if there's no recipient added */
3423 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3424 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3425 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3426 /* no recipient contents, then select contacts */
3427 modest_msg_edit_window_open_addressbook (window, NULL);
3431 g_object_ref (window);
3432 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3433 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3434 g_object_unref (window);
3437 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3438 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3439 g_object_unref (window);
3442 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3443 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3444 g_object_unref (window);
3448 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3449 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3450 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3451 g_object_unref (window);
3458 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3459 ModestMsgEditWindow *window)
3461 modest_msg_edit_window_offer_attach_file (window);
3465 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3467 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3469 return priv->clipboard_text;
3473 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3475 ModestMsgEditWindow *window)
3477 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3478 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3481 /* It could happen that the window was already closed */
3482 if (!GTK_WIDGET_VISIBLE (window))
3485 g_object_ref (window);
3486 text = gtk_clipboard_wait_for_text (selection_clipboard);
3488 if (priv->clipboard_text != NULL) {
3489 g_free (priv->clipboard_text);
3491 priv->clipboard_text = text;
3493 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3495 g_object_unref (window);
3498 static gboolean clipboard_owner_change_idle (gpointer userdata)
3500 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3501 ModestMsgEditWindowPrivate *priv;
3503 gdk_threads_enter ();
3504 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3505 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3507 priv->clipboard_owner_idle = 0;
3508 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3509 gdk_threads_leave ();
3515 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3517 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3518 if (priv->clipboard_owner_idle == 0) {
3519 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3520 clipboard_owner_change_idle,
3521 g_object_ref (window),
3527 subject_field_move_cursor (GtkEntry *entry,
3528 GtkMovementStep step,
3533 /* It could happen that the window was already closed */
3534 if (!GTK_WIDGET_VISIBLE (window))
3537 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3541 update_window_title (ModestMsgEditWindow *window)
3543 ModestMsgEditWindowPrivate *priv = NULL;
3544 const gchar *subject;
3546 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3547 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3548 if (subject == NULL || subject[0] == '\0')
3549 subject = _("mail_va_new_email");
3551 gtk_window_set_title (GTK_WINDOW (window), subject);
3557 body_insert_text (GtkTextBuffer *buffer,
3558 GtkTextIter *location,
3561 ModestMsgEditWindow *window)
3563 GtkTextIter end_iter;
3567 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3569 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3571 offset = gtk_text_iter_get_offset (&end_iter);
3572 utf8_len = g_utf8_strlen (text, len);
3574 if (offset + utf8_len > MAX_BODY_LENGTH) {
3575 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3576 if (offset < MAX_BODY_LENGTH)
3581 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3583 /* Prevent endless recursion */
3584 result = g_strndup (text, utf8_end - text);
3585 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3586 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3587 (gpointer) result, (gpointer) (utf8_end - text),
3589 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3593 if (offset + utf8_len > MAX_BODY_LENGTH) {
3594 if (priv->max_chars_banner == NULL) {
3595 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3596 _CS("ckdg_ib_maximum_characters_reached"));
3597 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3603 subject_field_changed (GtkEditable *editable,
3604 ModestMsgEditWindow *window)
3606 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3607 update_window_title (window);
3608 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3609 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3610 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3613 subject_field_insert_text (GtkEditable *editable,
3615 gint new_text_length,
3617 ModestMsgEditWindow *window)
3619 GString *result = g_string_new ("");
3621 gint result_len = 0;
3622 const gchar *entry_text = NULL;
3625 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3626 old_length = g_utf8_strlen (entry_text, -1);
3628 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3629 gunichar c = g_utf8_get_char_validated (current, 8);
3630 /* Invalid unichar, stop */
3636 result = g_string_append_unichar (result, c);
3640 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3641 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3644 /* Prevent endless recursion */
3645 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3646 g_signal_emit_by_name (editable, "insert-text",
3647 (gpointer) result->str, (gpointer) result->len,
3648 (gpointer) position, (gpointer) window);
3649 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3653 if (result_len + old_length > 1000) {
3654 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3655 _CS("ckdg_ib_maximum_characters_reached"));
3657 g_string_free (result, TRUE);
3661 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3664 ModestMsgEditWindowPrivate *priv = NULL;
3666 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3667 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3669 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3672 gtk_widget_show_all (priv->find_toolbar);
3673 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3675 gtk_widget_hide_all (priv->find_toolbar);
3676 gtk_widget_grab_focus (priv->msg_body);
3681 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3683 GtkTextIter *match_start,
3684 GtkTextIter *match_end)
3686 GtkTextIter end_iter;
3687 gchar *str_casefold;
3690 gchar *range_casefold;
3693 gboolean result = FALSE;
3700 gtk_text_iter_forward_to_end (&end_iter);
3702 str_casefold = g_utf8_casefold (str, -1);
3703 str_chars_n = strlen (str);
3705 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3706 range_casefold = g_utf8_casefold (range_text, -1);
3707 range_chars_n = strlen (range_casefold);
3709 if (range_chars_n < str_chars_n) {
3710 g_free (str_casefold);
3711 g_free (range_text);
3712 g_free (range_casefold);
3716 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3717 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3718 if (!g_utf8_collate (range_subtext, str_casefold)) {
3719 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3721 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3722 match_start, match_end, NULL)) {
3723 g_debug ("Matched string with collate, but not matched in model");
3725 g_free (found_text);
3727 g_free (range_subtext);
3731 g_free (str_casefold);
3732 g_free (range_text);
3733 g_free (range_casefold);
3740 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3741 ModestMsgEditWindow *window)
3743 gchar *current_search = NULL;
3744 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3746 GtkTextIter selection_start, selection_end;
3747 GtkTextIter match_start, match_end;
3748 gboolean continue_search = FALSE;
3750 if (message_is_empty (window)) {
3751 g_free (priv->last_search);
3752 priv->last_search = NULL;
3753 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3757 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3758 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3759 g_free (current_search);
3760 g_free (priv->last_search);
3761 priv->last_search = NULL;
3762 /* Information banner about empty search */
3763 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3767 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3768 continue_search = TRUE;
3770 g_free (priv->last_search);
3771 priv->last_search = g_strdup (current_search);
3774 if (continue_search) {
3775 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3776 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3777 &match_start, &match_end);
3779 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3781 GtkTextIter buffer_start;
3782 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3783 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3784 &match_start, &match_end);
3786 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3789 /* Mark as selected the string found in search */
3791 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3792 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3793 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3795 g_free (priv->last_search);
3796 priv->last_search = NULL;
3798 g_free (current_search);
3802 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3804 ModestMsgEditWindowPrivate *priv;
3806 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3811 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3814 ModestMsgEditWindowPrivate *priv;
3816 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3821 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3822 ModestMsgEditWindow *window)
3824 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3828 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3831 ModestMsgEditWindowPrivate *priv;
3832 TnyHeader *header = NULL;
3834 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3835 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3837 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3839 if (priv->draft_msg != NULL) {
3840 g_object_unref (priv->draft_msg);
3843 if (draft != NULL) {
3844 g_object_ref (draft);
3845 header = tny_msg_get_header (draft);
3846 if (priv->msg_uid) {
3847 g_free (priv->msg_uid);
3848 priv->msg_uid = NULL;
3850 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3853 priv->draft_msg = draft;
3857 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3858 GtkTextIter *start, GtkTextIter *end,
3861 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3862 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3865 if (tag == NULL) return;
3866 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3867 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3868 replace_with_images (window, priv->images);
3873 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3876 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3878 g_return_if_fail (TNY_IS_MIME_PART (part));
3879 tny_list_prepend (priv->attachments, (GObject *) part);
3880 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3881 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3882 gtk_widget_show_all (priv->attachments_caption);
3883 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3887 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3889 ModestMsgEditWindowPrivate *priv;
3891 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3892 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3894 return priv->msg_uid;
3898 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3899 ModestMsgEditWindowWidgetType widget_type)
3901 ModestMsgEditWindowPrivate *priv;
3903 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3904 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3906 switch (widget_type) {
3907 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3908 return priv->msg_body;
3910 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3911 return priv->to_field;
3913 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3914 return priv->cc_field;
3916 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3917 return priv->bcc_field;
3919 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3920 return priv->subject_field;
3922 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3923 return priv->attachments_view;
3931 remove_tags (WPTextBuffer *buffer)
3933 GtkTextIter start, end;
3935 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3936 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3938 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3942 on_account_removed (TnyAccountStore *account_store,
3943 TnyAccount *account,
3946 /* Do nothing if it's a store account, because we use the
3947 transport to send the messages */
3948 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3949 const gchar *parent_acc = NULL;
3950 const gchar *our_acc = NULL;
3952 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3953 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3954 /* Close this window if I'm showing a message of the removed account */
3955 if (strcmp (parent_acc, our_acc) == 0)
3956 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3960 static void update_signature (ModestMsgEditWindow *self,
3961 const gchar *old_account,
3962 const gchar *new_account)
3964 ModestMsgEditWindowPrivate *priv;
3965 gboolean has_old_signature, has_new_signature;
3967 GtkTextIter match_start, match_end;
3968 ModestAccountMgr *mgr;
3970 gchar *full_signature;
3972 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3974 gtk_text_buffer_begin_user_action (priv->text_buffer);
3976 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3977 mgr = modest_runtime_get_account_mgr ();
3981 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3982 if (has_old_signature) {
3983 full_signature = g_strconcat ("\n--\n", signature, NULL);
3984 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3985 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3987 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3988 &match_start, &match_end, NULL)) {
3991 g_free (full_signature);
3996 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3997 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3998 if (has_new_signature) {
3999 full_signature = g_strconcat ("\n--\n", signature, NULL);
4000 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4001 g_free (full_signature);
4004 gtk_text_buffer_end_user_action (priv->text_buffer);
4007 static void update_branding (ModestMsgEditWindow *self,
4008 const gchar *new_account)
4010 ModestMsgEditWindowPrivate *priv;
4011 ModestAccountMgr *mgr;
4012 const GdkPixbuf *new_icon = NULL;
4013 gchar *new_label = NULL;
4015 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4017 mgr = modest_runtime_get_account_mgr ();
4019 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4021 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4022 gtk_widget_show (priv->brand_icon);
4024 gtk_widget_hide (priv->brand_icon);
4027 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4028 gtk_widget_show (priv->brand_label);
4031 gtk_widget_hide (priv->brand_label);
4036 from_field_changed (HildonPickerButton *button,
4037 ModestMsgEditWindow *self)
4039 ModestMsgEditWindowPrivate *priv;
4040 gchar *old_account, *new_account;
4042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4044 old_account = priv->last_from_account;
4045 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4046 new_account = priv->last_from_account;
4048 update_signature (self, old_account, new_account);
4049 update_branding (self, new_account);
4053 typedef struct _MessageSettingsHelper {
4054 ModestMsgEditWindow *window;
4055 GSList *priority_group;
4056 GSList *format_group;
4057 GtkToggleButton *current_priority;
4058 GtkToggleButton *current_format;
4059 } MessageSettingsHelper;
4062 on_priority_toggle (GtkToggleButton *button,
4063 MessageSettingsHelper *helper)
4066 ModestMsgEditWindowPrivate *priv;
4068 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4069 if (gtk_toggle_button_get_active (button)) {
4071 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4072 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4073 if ((node_button != button) &&
4074 gtk_toggle_button_get_active (node_button)) {
4075 gtk_toggle_button_set_active (node_button, FALSE);
4078 helper->current_priority = button;
4080 gboolean found = FALSE;
4081 /* If no one is active, activate it again */
4082 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4083 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4084 if (gtk_toggle_button_get_active (node_button)) {
4090 gtk_toggle_button_set_active (button, TRUE);
4096 on_format_toggle (GtkToggleButton *button,
4097 MessageSettingsHelper *helper)
4100 ModestMsgEditWindowPrivate *priv;
4102 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4103 if (gtk_toggle_button_get_active (button)) {
4105 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4106 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4107 if ((node_button != button) &&
4108 gtk_toggle_button_get_active (node_button)) {
4109 gtk_toggle_button_set_active (node_button, FALSE);
4112 helper->current_format = button;
4114 gboolean found = FALSE;
4115 /* If no one is active, activate it again */
4116 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4117 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4118 if (gtk_toggle_button_get_active (node_button)) {
4124 gtk_toggle_button_set_active (button, TRUE);
4131 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4136 GtkWidget *priority_hbox;
4137 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4138 GtkWidget *captioned;
4139 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4140 GtkWidget *format_hbox;
4141 GtkWidget *html_toggle, *text_toggle;
4142 ModestMsgEditWindowPrivate *priv;
4143 MessageSettingsHelper helper = {0,};
4145 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4146 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4147 helper.window = window;
4148 helper.priority_group = NULL;
4149 helper.format_group = NULL;
4151 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4152 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4154 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4155 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4156 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4157 vbox = gtk_vbox_new (FALSE, 0);
4158 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4159 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4160 gtk_container_add (GTK_CONTAINER (align), vbox);
4161 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4162 gtk_widget_show (align);
4163 gtk_widget_show (vbox);
4165 /* Priority toggles */
4166 priority_hbox = gtk_hbox_new (TRUE, 0);
4167 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4168 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4169 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4170 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4171 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4172 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4173 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4174 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4175 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4176 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4177 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4178 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4179 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4180 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4181 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4182 gtk_widget_show_all (priority_hbox);
4183 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4184 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4185 gtk_widget_show (captioned);
4186 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4188 /* format toggles */
4189 format_hbox = gtk_hbox_new (TRUE, 0);
4190 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4191 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4192 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4193 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4194 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4195 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4196 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4197 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4198 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4199 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4200 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4201 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4202 gtk_widget_show_all (format_hbox);
4203 gtk_widget_show (format_hbox);
4204 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4207 g_object_unref (title_sizegroup);
4208 g_object_unref (value_sizegroup);
4210 /* Set current values */
4211 switch (priv->priority_flags) {
4212 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4213 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4214 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4216 case TNY_HEADER_FLAG_LOW_PRIORITY:
4217 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4218 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4221 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4222 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4226 switch (modest_msg_edit_window_get_format (window)) {
4227 case MODEST_MSG_EDIT_FORMAT_TEXT:
4228 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4229 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4231 case MODEST_MSG_EDIT_FORMAT_HTML:
4233 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4234 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4238 /* Signal connects */
4239 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4240 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4241 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4242 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4243 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4245 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4246 GTK_WINDOW (dialog), GTK_WINDOW (window));
4248 /* Save settings if the user clicked on done */
4249 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4250 TnyHeaderFlags flags;
4251 ModestMsgEditFormat old_format, new_format;
4253 /* Set priority flags */
4254 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4255 if (priv->priority_flags != flags)
4256 modest_msg_edit_window_set_priority_flags (window, flags);
4258 /* Set edit format */
4259 old_format = modest_msg_edit_window_get_format (window);
4260 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4261 if (old_format != new_format) {
4262 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4263 modest_msg_edit_window_set_file_format (window, file_format);
4267 gtk_widget_destroy (dialog);
4268 g_slist_free (helper.priority_group);
4272 on_message_settings (GtkAction *action,
4273 ModestMsgEditWindow *window)
4275 modest_msg_edit_window_show_msg_settings_dialog (window);
4279 on_cc_button_toggled (HildonCheckButton *button,
4280 ModestMsgEditWindow *window)
4282 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4284 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4285 hildon_check_button_get_active (button));
4289 on_bcc_button_toggled (HildonCheckButton *button,
4290 ModestMsgEditWindow *window)
4292 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4294 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4295 hildon_check_button_get_active (button));
4299 setup_menu (ModestMsgEditWindow *self)
4301 ModestMsgEditWindowPrivate *priv = NULL;
4303 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4305 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4307 /* Settings menu buttons */
4308 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4309 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4311 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4312 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4313 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4315 priv->cc_button = hildon_check_button_new (0);
4316 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4317 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4319 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4321 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4322 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4323 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4324 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4326 priv->bcc_button = hildon_check_button_new (0);
4327 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4328 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4330 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4332 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4333 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4334 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4335 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4337 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4338 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4339 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4340 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4341 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4343 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4344 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4345 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4346 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4347 APP_MENU_CALLBACK (on_message_settings),
4349 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4350 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4355 emit_open_addressbook (GtkButton *button,
4356 ModestRecptEditor *editor)
4358 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4362 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4363 const gchar *label, GtkWidget *control)
4365 GtkWidget *abook_button;
4368 GtkWidget *label_widget;
4370 box = gtk_hbox_new (FALSE, 0);
4372 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4373 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4375 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4376 label_widget = gtk_label_new (label);
4377 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4378 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4380 gtk_container_add (GTK_CONTAINER (align), abook_button);
4381 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4382 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4383 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4384 if (title_size_group)
4385 gtk_size_group_add_widget (title_size_group, label_widget);
4386 if (value_size_group)
4387 gtk_size_group_add_widget (value_size_group, control);
4389 g_signal_connect (G_OBJECT (abook_button), "clicked",
4390 G_CALLBACK (emit_open_addressbook), control);
4396 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4398 ModestMsgEditWindowPrivate *priv = NULL;
4400 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4402 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4403 priv->max_chars_banner = NULL;