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 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
945 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
946 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
948 from_send_hbox = gtk_hbox_new (FALSE, 0);
949 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
950 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
952 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
953 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
954 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, TRUE, TRUE, 0);
957 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
958 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
959 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
960 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
961 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
962 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
963 gtk_box_pack_start (GTK_BOX (priv->header_box), branding_box, FALSE, FALSE, 0);
964 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
966 init_wp_text_view_style ();
968 priv->msg_body = modest_wp_text_view_new ();
971 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
972 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
973 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
974 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
975 #if (GTK_MINOR_VERSION >= 10)
976 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
977 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
979 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
980 deserialize_type, TRUE);
982 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
984 priv->find_toolbar = hildon_find_toolbar_new (NULL);
985 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
987 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
989 priv->pannable = hildon_pannable_area_new ();
991 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
993 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
994 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
995 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
997 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
998 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
999 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1001 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1002 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1004 window_box = gtk_vbox_new (FALSE, 0);
1005 gtk_container_add (GTK_CONTAINER(obj), window_box);
1007 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1009 /* Set window icon */
1010 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1012 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1013 g_object_unref (window_icon);
1018 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1020 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1022 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1023 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1024 priv->clipboard_change_handler_id))
1025 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1026 priv->clipboard_change_handler_id);
1027 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1028 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1029 priv->default_clipboard_change_handler_id))
1030 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1031 priv->default_clipboard_change_handler_id);
1033 if (priv->account_removed_handler_id &&
1034 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1035 priv->account_removed_handler_id))
1036 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1037 priv->account_removed_handler_id);
1041 modest_msg_edit_window_finalize (GObject *obj)
1043 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1045 if (priv->max_chars_banner) {
1046 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1047 priv->max_chars_banner = FALSE;
1050 /* Sanity check: shouldn't be needed, the window mgr should
1051 call this function before */
1052 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1054 if (priv->font_dialog != NULL) {
1055 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1058 if (priv->clipboard_text != NULL) {
1059 g_free (priv->clipboard_text);
1060 priv->clipboard_text = NULL;
1063 if (priv->draft_msg != NULL) {
1064 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1065 if (TNY_IS_HEADER (header)) {
1066 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1067 modest_window_mgr_unregister_header (mgr, header);
1069 g_object_unref (priv->draft_msg);
1070 priv->draft_msg = NULL;
1072 if (priv->outbox_msg != NULL) {
1073 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1074 if (TNY_IS_HEADER (header)) {
1075 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1076 modest_window_mgr_unregister_header (mgr, header);
1078 g_object_unref (priv->outbox_msg);
1079 priv->outbox_msg = NULL;
1081 if (priv->correct_scroll_idle > 0) {
1082 g_source_remove (priv->correct_scroll_idle);
1083 priv->correct_scroll_idle = 0;
1085 if (priv->scroll_drag_timeout_id > 0) {
1086 g_source_remove (priv->scroll_drag_timeout_id);
1087 priv->scroll_drag_timeout_id = 0;
1089 if (priv->clipboard_owner_idle > 0) {
1090 g_source_remove (priv->clipboard_owner_idle);
1091 priv->clipboard_owner_idle = 0;
1093 if (priv->original_account_name)
1094 g_free (priv->original_account_name);
1095 if (priv->original_mailbox)
1096 g_free (priv->original_mailbox);
1097 g_free (priv->msg_uid);
1098 g_free (priv->last_search);
1099 g_free (priv->references);
1100 g_free (priv->in_reply_to);
1101 g_object_unref (priv->attachments);
1102 g_object_unref (priv->images);
1104 /* This had to stay alive for as long as the picker that used it: */
1105 modest_pair_list_free (priv->from_field_protos);
1107 G_OBJECT_CLASS(parent_class)->finalize (obj);
1111 pixbuf_size_prepared (GdkPixbufLoader *loader,
1114 ModestMsgEditWindow *self)
1116 gint new_height, new_width;
1119 new_height = height;
1123 if (width > IMAGE_MAX_WIDTH) {
1124 new_height = height * IMAGE_MAX_WIDTH / width;
1125 new_width = IMAGE_MAX_WIDTH;
1128 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1132 pixbuf_from_stream (TnyStream *stream,
1133 const gchar *mime_type,
1134 guint64 *stream_size,
1135 ModestMsgEditWindow *self)
1137 GdkPixbufLoader *loader;
1140 GError *error = NULL;
1144 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1146 if (loader == NULL) {
1151 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1153 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1155 tny_stream_reset (TNY_STREAM (stream));
1156 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1157 unsigned char read_buffer[128];
1159 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1161 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1164 /* Allow some UI responsiveness */
1165 while (gtk_events_pending ())
1166 gtk_main_iteration ();
1168 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1170 gdk_pixbuf_loader_close (loader, &error);
1173 g_error_free (error);
1174 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1176 g_object_ref (pixbuf);
1177 g_object_unref (loader);
1182 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1183 GdkPixbuf *new_pixbuf;
1185 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1186 gdk_pixbuf_get_width (pixbuf);
1187 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1188 g_object_unref (pixbuf);
1189 pixbuf = new_pixbuf;
1193 *stream_size = size;
1199 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1201 ModestMsgEditWindowPrivate *priv;
1204 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1206 g_object_ref (self);
1207 for (iter = tny_list_create_iterator (attachments);
1208 !tny_iterator_is_done (iter);
1209 tny_iterator_next (iter)) {
1210 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1211 const gchar *cid = tny_mime_part_get_content_id (part);
1212 const gchar *mime_type = tny_mime_part_get_content_type (part);
1213 if ((cid != NULL)&&(mime_type != NULL)) {
1214 guint64 stream_size;
1215 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1216 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1219 g_object_unref (stream);
1221 if (pixbuf != NULL) {
1222 priv->images_count ++;
1223 priv->images_size += stream_size;
1224 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1225 g_object_unref (pixbuf);
1228 g_object_unref (part);
1230 g_object_unref (iter);
1231 g_object_unref (self);
1235 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1237 TnyMimePart *parent = NULL;
1238 const gchar *content_type = NULL;
1239 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1241 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1243 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1244 parent = g_object_ref (msg);
1245 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1246 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1249 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1250 iter = tny_list_create_iterator (parts);
1251 while (!tny_iterator_is_done (iter)) {
1253 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1254 content_type = tny_mime_part_get_content_type (part);
1255 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1259 g_object_unref (part);
1261 tny_iterator_next (iter);
1263 g_object_unref (iter);
1264 g_object_unref (parts);
1267 if (parent != NULL) {
1268 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1271 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1272 iter = tny_list_create_iterator (parts);
1273 while (!tny_iterator_is_done (iter)) {
1275 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1276 content_type = tny_mime_part_get_content_type (part);
1277 if (content_type && g_str_has_prefix (content_type, "image/")) {
1278 tny_list_prepend (priv->images, (GObject *) part);
1280 g_object_unref (part);
1281 tny_iterator_next (iter);
1283 g_object_unref (iter);
1284 g_object_unref (parts);
1285 g_object_unref (parent);
1290 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1293 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1295 for (iter = tny_list_create_iterator (attachments) ;
1296 !tny_iterator_is_done (iter);
1297 tny_iterator_next (iter)) {
1298 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1299 const gchar *cid = tny_mime_part_get_content_id (part);
1301 char *invalid = NULL;
1302 gint int_cid = strtol (cid, &invalid, 10);
1303 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1304 priv->next_cid = int_cid + 1;
1307 g_object_unref (part);
1309 g_object_unref (iter);
1313 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1316 gchar *to, *cc, *bcc, *subject;
1318 ModestMsgEditWindowPrivate *priv;
1319 ModestWindowPrivate *parent_priv;
1321 TnyHeaderFlags priority_flags;
1322 TnyFolder *msg_folder;
1323 gboolean is_html = FALSE;
1324 gboolean field_view_set;
1326 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1327 g_return_if_fail (TNY_IS_MSG (msg));
1329 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1330 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1332 header = tny_msg_get_header (msg);
1333 to = tny_header_dup_to (header);
1334 cc = tny_header_dup_cc (header);
1335 bcc = tny_header_dup_bcc (header);
1336 subject = tny_header_dup_subject (header);
1338 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1339 priority_flags = tny_header_get_priority (header);
1342 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1344 field_view_set = TRUE;
1346 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1347 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1348 gtk_widget_show (priv->cc_caption);
1349 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1350 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1351 gtk_widget_hide (priv->cc_caption);
1352 field_view_set = FALSE;
1354 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1356 field_view_set = TRUE;
1358 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1359 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1360 gtk_widget_show (priv->bcc_caption);
1361 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1362 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1363 gtk_widget_hide (priv->bcc_caption);
1364 field_view_set = FALSE;
1366 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1370 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1371 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1374 update_window_title (self);
1376 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1377 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1379 if ((body == NULL)||(body[0] == '\0')) {
1381 body = modest_text_utils_convert_to_html ("");
1384 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1385 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1388 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1391 /* Add attachments to the view */
1392 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1393 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1394 if (tny_list_get_length (priv->attachments) == 0) {
1395 gtk_widget_hide (priv->attachments_caption);
1397 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1398 gtk_widget_show_all (priv->attachments_caption);
1400 get_related_images (self, msg);
1401 update_next_cid (self, priv->attachments);
1402 update_next_cid (self, priv->images);
1403 replace_with_images (self, priv->images);
1405 if (preserve_is_rich && !is_html) {
1406 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1407 /* Get the default format required from configuration */
1408 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1409 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1412 /* Set the default focus depending on having already a To: field or not */
1413 if ((!to)||(*to == '\0')) {
1414 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1416 gtk_widget_grab_focus (priv->msg_body);
1419 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1421 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1422 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1424 modest_msg_edit_window_set_modified (self, FALSE);
1426 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1427 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1428 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1429 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1431 if (priv->msg_uid) {
1432 g_free (priv->msg_uid);
1433 priv->msg_uid = NULL;
1436 /* we should set a reference to the incoming message if it is a draft */
1437 msg_folder = tny_msg_get_folder (msg);
1439 if (modest_tny_folder_is_local_folder (msg_folder)) {
1440 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1441 if (type == TNY_FOLDER_TYPE_INVALID)
1442 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1444 if (type == TNY_FOLDER_TYPE_DRAFTS)
1445 priv->draft_msg = g_object_ref(msg);
1446 if (type == TNY_FOLDER_TYPE_OUTBOX)
1447 priv->outbox_msg = g_object_ref(msg);
1448 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1450 g_object_unref (msg_folder);
1461 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1463 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1464 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1465 GtkWidget *placeholder;
1466 GtkWidget *tool_item;
1471 GtkWidget *sizes_menu;
1472 GtkWidget *fonts_menu;
1478 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1479 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1480 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1481 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1483 /* Font color placeholder */
1484 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1485 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1488 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1489 priv->font_color_button = hildon_color_button_new ();
1490 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1491 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1492 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1493 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1494 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1495 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1496 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1497 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1499 G_CALLBACK (modest_msg_edit_window_color_button_change),
1502 /* Font size and face placeholder */
1503 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1504 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1506 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1507 priv->size_tool_button_label = gtk_label_new (NULL);
1508 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1509 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1510 size_text, "</span>", NULL);
1511 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1512 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1514 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1515 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1516 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1517 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1518 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1519 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1520 gtk_widget_set_sensitive (arrow, FALSE);
1521 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1522 sizes_menu = gtk_menu_new ();
1523 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1524 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1527 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1528 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1530 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1534 if (wp_font_size[size_index] == 12)
1535 priv->current_size_index = size_index;
1539 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1540 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1541 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1542 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1543 priv->font_size_toolitem = tool_item;
1546 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1547 priv->font_tool_button_label = gtk_label_new (NULL);
1548 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1549 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1550 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1552 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1553 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1554 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1555 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1556 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1557 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1558 gtk_widget_set_sensitive (arrow, FALSE);
1559 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1560 fonts_menu = gtk_menu_new ();
1561 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1562 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1565 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1567 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1568 0, wp_get_font_name (font_index),
1571 if (font_index == DEFAULT_FONT)
1572 priv->current_face_index = font_index;
1574 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1575 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1576 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1577 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1578 priv->font_face_toolitem = tool_item;
1580 /* Set expand and homogeneous for remaining items */
1581 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1582 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1583 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1584 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1585 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1586 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1588 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1589 will not show the tool items added to the placeholders) */
1590 gtk_widget_show_all (parent_priv->toolbar);
1592 /* Set the no show all *after* showing all items. We do not
1593 want the toolbar to be shown with a show all because it
1594 could go agains the gconf setting regarding showing or not
1595 the toolbar of the editor window */
1596 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1602 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1605 ModestWindowPrivate *parent_priv;
1606 ModestMsgEditWindowPrivate *priv;
1607 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1608 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1609 ModestWindowMgr *mgr = NULL;
1611 g_return_val_if_fail (msg, NULL);
1612 g_return_val_if_fail (account_name, NULL);
1614 mgr = modest_runtime_get_window_mgr ();
1616 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1619 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1621 /* Menubar. Update the state of some toggles */
1622 priv->from_field_protos = get_transports ();
1623 priv->original_mailbox = NULL;
1624 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1625 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1626 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1627 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1628 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1629 priv->original_mailbox = g_strdup (mailbox);
1630 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1631 /* We set the first mailbox as the active mailbox */
1632 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1633 if (priv->original_mailbox != NULL)
1634 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1635 (gpointer) priv->original_mailbox);
1637 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1638 (gpointer) account_name);
1640 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1642 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1643 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1644 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1646 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1647 hildon_touch_selector_get_current_text
1648 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1649 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1650 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1653 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1655 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1657 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1658 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1660 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1662 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1663 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1664 /* Add common dimming rules */
1665 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1666 modest_msg_edit_window_toolbar_dimming_entries,
1667 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1668 MODEST_WINDOW (obj));
1669 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1670 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1671 MODEST_WINDOW (obj));
1672 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1673 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1674 MODEST_WINDOW (obj));
1675 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1676 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1677 MODEST_WINDOW (obj));
1678 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1679 G_CALLBACK (modest_ui_dimming_rules_on_send),
1680 MODEST_WINDOW (obj));
1681 /* Insert dimming rules group for this window */
1682 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1683 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1685 /* Setup app menu */
1686 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1688 /* Checks the dimming rules */
1689 g_object_unref (toolbar_rules_group);
1690 g_object_unref (clipboard_rules_group);
1691 gtk_widget_hide (priv->priority_icon);
1692 gtk_widget_queue_resize (priv->subject_box);
1693 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1695 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1697 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1698 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1699 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1700 priv->update_caption_visibility = TRUE;
1702 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1704 /* Track account-removed signal, this window should be closed
1705 in the case we're creating a mail associated to the account
1707 priv->account_removed_handler_id =
1708 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1710 G_CALLBACK(on_account_removed),
1713 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1715 return (ModestWindow*) obj;
1719 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1721 GString **string_buffer = (GString **) user_data;
1723 *string_buffer = g_string_append (*string_buffer, buffer);
1729 * @result: A new string which should be freed with g_free().
1732 get_formatted_data (ModestMsgEditWindow *edit_window)
1734 ModestMsgEditWindowPrivate *priv;
1735 GString *string_buffer = g_string_new ("");
1737 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1739 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1741 modest_text_utils_hyperlinkify (string_buffer);
1743 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1745 return g_string_free (string_buffer, FALSE);
1750 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1753 const gchar *account_name;
1754 ModestMsgEditWindowPrivate *priv;
1755 TnyIterator *att_iter;
1756 const gchar *picker_active_id;
1758 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1760 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1762 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1763 g_return_val_if_fail (picker_active_id, NULL);
1764 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1766 /* don't free these (except from) */
1767 data = g_slice_new0 (MsgData);
1768 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1769 data->account_name = g_strdup (account_name);
1770 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1771 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1772 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1773 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1774 data->references = g_strdup (priv->references);
1775 data->in_reply_to = g_strdup (priv->in_reply_to);
1776 if (priv->draft_msg) {
1777 data->draft_msg = g_object_ref (priv->draft_msg);
1778 } else if (priv->outbox_msg) {
1779 data->draft_msg = g_object_ref (priv->outbox_msg);
1781 data->draft_msg = NULL;
1784 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1786 gtk_text_buffer_get_bounds (buf, &b, &e);
1787 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1789 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1790 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1792 data->html_body = NULL;
1794 /* deep-copy the data */
1795 att_iter = tny_list_create_iterator (priv->attachments);
1796 data->attachments = NULL;
1797 while (!tny_iterator_is_done (att_iter)) {
1798 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1799 if (!(TNY_IS_MIME_PART(part))) {
1800 g_warning ("strange data in attachment list");
1801 g_object_unref (part);
1802 tny_iterator_next (att_iter);
1805 data->attachments = g_list_append (data->attachments,
1807 tny_iterator_next (att_iter);
1809 g_object_unref (att_iter);
1811 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1812 att_iter = tny_list_create_iterator (priv->images);
1813 data->images = NULL;
1814 while (!tny_iterator_is_done (att_iter)) {
1815 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1817 if (!(TNY_IS_MIME_PART(part))) {
1818 g_warning ("strange data in attachment list");
1819 g_object_unref (part);
1820 tny_iterator_next (att_iter);
1823 cid = tny_mime_part_get_content_id (part);
1825 gchar *image_tag_id;
1826 GtkTextTag *image_tag;
1828 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1829 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1830 g_free (image_tag_id);
1832 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1834 ((gtk_text_iter_has_tag (&iter, image_tag))||
1835 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1836 data->images = g_list_append (data->images,
1837 g_object_ref (part));
1839 g_object_unref (part);
1840 tny_iterator_next (att_iter);
1842 g_object_unref (att_iter);
1844 data->priority_flags = priv->priority_flags;
1851 unref_gobject (GObject *obj, gpointer data)
1853 if (!G_IS_OBJECT(obj))
1855 g_object_unref (obj);
1859 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1862 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1870 g_free (data->from);
1871 g_free (data->subject);
1872 g_free (data->plain_body);
1873 g_free (data->html_body);
1874 g_free (data->account_name);
1875 g_free (data->references);
1876 g_free (data->in_reply_to);
1878 if (data->draft_msg != NULL) {
1879 g_object_unref (data->draft_msg);
1880 data->draft_msg = NULL;
1883 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1884 g_list_free (data->attachments);
1885 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1886 g_list_free (data->images);
1888 g_slice_free (MsgData, data);
1892 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1894 guint64 *parts_size)
1896 ModestMsgEditWindowPrivate *priv;
1898 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1900 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1902 /* TODO: add images */
1903 *parts_size += priv->images_size;
1904 *parts_count += priv->images_count;
1909 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1912 ModestMsgEditWindowPrivate *priv = NULL;
1913 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1915 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1917 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1919 return MODEST_MSG_EDIT_FORMAT_HTML;
1921 return MODEST_MSG_EDIT_FORMAT_TEXT;
1925 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1926 ModestMsgEditFormat format)
1928 ModestMsgEditWindowPrivate *priv;
1929 ModestWindowPrivate *parent_priv;
1931 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1933 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1936 case MODEST_MSG_EDIT_FORMAT_HTML:
1937 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1938 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1940 case MODEST_MSG_EDIT_FORMAT_TEXT:
1941 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1942 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1945 g_return_if_reached ();
1949 ModestMsgEditFormatState *
1950 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1952 ModestMsgEditFormatState *format_state = NULL;
1953 ModestMsgEditWindowPrivate *priv;
1954 WPTextBufferFormat *buffer_format;
1956 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1958 buffer_format = g_new0 (WPTextBufferFormat, 1);
1959 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1961 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1963 format_state = g_new0 (ModestMsgEditFormatState, 1);
1964 format_state->bold = buffer_format->bold&0x1;
1965 format_state->italics = buffer_format->italic&0x1;
1966 format_state->bullet = buffer_format->bullet&0x1;
1967 format_state->color = buffer_format->color;
1968 format_state->font_size = buffer_format->font_size;
1969 format_state->font_family = wp_get_font_name (buffer_format->font);
1970 format_state->justification = buffer_format->justification;
1971 g_free (buffer_format);
1973 return format_state;
1978 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1979 const ModestMsgEditFormatState *format_state)
1981 ModestMsgEditWindowPrivate *priv;
1982 WPTextBufferFormat *buffer_format;
1983 WPTextBufferFormat *current_format;
1985 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1986 g_return_if_fail (format_state != NULL);
1988 buffer_format = g_new0 (WPTextBufferFormat, 1);
1989 current_format = g_new0 (WPTextBufferFormat, 1);
1991 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1992 gtk_widget_grab_focus (priv->msg_body);
1993 buffer_format->bold = (format_state->bold != FALSE);
1994 buffer_format->italic = (format_state->italics != FALSE);
1995 buffer_format->color = format_state->color;
1996 buffer_format->font_size = format_state->font_size;
1997 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1998 buffer_format->justification = format_state->justification;
1999 buffer_format->bullet = format_state->bullet;
2001 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2003 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2004 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2005 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2006 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2007 buffer_format->cs.font = (buffer_format->font != current_format->font);
2008 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2009 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2011 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2012 if (buffer_format->cs.bold) {
2013 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2014 GINT_TO_POINTER (buffer_format->bold&0x1));
2016 if (buffer_format->cs.italic) {
2017 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2018 GINT_TO_POINTER (buffer_format->italic&0x1));
2020 if (buffer_format->cs.color) {
2021 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2022 GINT_TO_POINTER (&(buffer_format->color)));
2024 if (buffer_format->cs.font_size) {
2025 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2026 GINT_TO_POINTER (buffer_format->font_size));
2028 if (buffer_format->cs.justification) {
2029 switch (buffer_format->justification) {
2030 case GTK_JUSTIFY_LEFT:
2031 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2032 GINT_TO_POINTER(TRUE));
2034 case GTK_JUSTIFY_CENTER:
2035 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2036 GINT_TO_POINTER(TRUE));
2038 case GTK_JUSTIFY_RIGHT:
2039 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2040 GINT_TO_POINTER(TRUE));
2047 if (buffer_format->cs.font) {
2048 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2049 GINT_TO_POINTER (buffer_format->font));
2051 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2052 if (buffer_format->cs.bullet) {
2053 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2054 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2056 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2058 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2060 g_free (buffer_format);
2061 g_free (current_format);
2063 /* Check dimming rules */
2064 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2065 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2069 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2071 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2073 ModestWindowPrivate *parent_priv;
2074 ModestMsgEditWindowPrivate *priv;
2076 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2077 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2079 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2080 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2081 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2082 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2084 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2085 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2086 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2089 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2091 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2092 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2094 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2095 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2097 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2098 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2101 switch (buffer_format->justification)
2103 case GTK_JUSTIFY_LEFT:
2104 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2106 case GTK_JUSTIFY_CENTER:
2107 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2109 case GTK_JUSTIFY_RIGHT:
2110 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2117 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2119 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2120 G_CALLBACK (modest_msg_edit_window_color_button_change),
2122 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2123 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2124 G_CALLBACK (modest_msg_edit_window_color_button_change),
2127 if (priv->current_size_index != buffer_format->font_size) {
2131 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2132 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2136 priv->current_size_index = buffer_format->font_size;
2138 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2139 markup = g_strconcat ("<span font_family='Sans'>",
2140 size_text, "</span>", NULL);
2142 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2146 gtk_tree_path_free (path);
2149 if (priv->current_face_index != buffer_format->font) {
2153 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2154 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2158 priv->current_face_index = buffer_format->font;
2159 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2160 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2161 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2168 g_free (buffer_format);
2172 #ifdef MODEST_HILDON_VERSION_0
2174 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2177 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2178 ModestMsgEditWindowPrivate *priv;
2179 GtkWidget *dialog = NULL;
2181 GdkColor *new_color = NULL;
2183 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2184 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2186 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2187 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2188 g_free (buffer_format);
2190 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2191 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2192 if (new_color != NULL) {
2193 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2194 (gpointer) new_color);
2197 gtk_widget_destroy (dialog);
2202 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2205 ModestMsgEditWindowPrivate *priv;
2206 GtkWidget *dialog = NULL;
2208 GdkColor *old_color = NULL;
2209 const GdkColor *new_color = NULL;
2211 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2212 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2214 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2215 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2217 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2218 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2219 if (new_color != NULL)
2220 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2222 gtk_widget_destroy (dialog);
2228 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2231 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2232 ModestMsgEditWindowPrivate *priv;
2233 GtkWidget *dialog = NULL;
2235 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2236 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2238 dialog = hildon_color_chooser_new ();
2239 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2240 g_free (buffer_format);
2242 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2244 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2245 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2248 gtk_widget_destroy (dialog);
2253 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2256 ModestMsgEditWindowPrivate *priv;
2257 GtkWidget *dialog = NULL;
2258 GdkColor *old_color = NULL;
2260 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2261 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2263 dialog = hildon_color_chooser_new ();
2264 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2266 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2268 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2269 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2271 gtk_widget_destroy (dialog);
2274 #endif /*!MODEST_HILDON_VERSION_0*/
2279 create_stream_for_uri (const gchar* uri)
2284 TnyStream *result = NULL;
2286 GnomeVFSHandle *handle = NULL;
2287 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2288 if (test == GNOME_VFS_OK) {
2289 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2290 /* Streams over OBEX (Bluetooth) are not seekable but
2291 * we expect them to be (we might need to read them
2292 * several times). So if this is a Bluetooth URI just
2293 * read the whole file into memory (this is not a fast
2294 * protocol so we can assume that these files are not
2295 * going to be very big) */
2296 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2297 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2298 TnyStream *memstream = tny_camel_mem_stream_new ();
2299 tny_stream_write_to_stream (vfssstream, memstream);
2300 g_object_unref (vfssstream);
2303 result = vfssstream;
2311 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2314 ModestMsgEditWindowPrivate *priv;
2315 GtkWidget *dialog = NULL;
2317 GSList *uris = NULL;
2318 GSList *uri_node = NULL;
2320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2322 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2323 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2324 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2326 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2328 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2329 GTK_WINDOW (dialog), GTK_WINDOW (window));
2331 response = gtk_dialog_run (GTK_DIALOG (dialog));
2333 case GTK_RESPONSE_OK:
2335 gchar *current_folder;
2336 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2337 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2338 if (current_folder && current_folder != '\0') {
2340 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2341 current_folder, &err);
2343 g_debug ("Error storing latest used folder: %s", err->message);
2347 g_free (current_folder);
2353 gtk_widget_destroy (dialog);
2355 g_object_ref (window);
2356 /* The operation could take some time so allow the dialog to be closed */
2357 while (gtk_events_pending ())
2358 gtk_main_iteration ();
2360 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2362 GnomeVFSHandle *handle = NULL;
2363 GnomeVFSResult result;
2364 GtkTextIter position;
2365 GtkTextMark *insert_mark;
2367 uri = (const gchar *) uri_node->data;
2368 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2369 if (result == GNOME_VFS_OK) {
2371 GnomeVFSFileInfo *info;
2372 gchar *filename, *basename, *escaped_filename;
2373 TnyMimePart *mime_part;
2375 const gchar *mime_type = NULL;
2376 GnomeVFSURI *vfs_uri;
2377 guint64 stream_size;
2379 gnome_vfs_close (handle);
2380 vfs_uri = gnome_vfs_uri_new (uri);
2382 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2383 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2384 g_free (escaped_filename);
2385 gnome_vfs_uri_unref (vfs_uri);
2386 info = gnome_vfs_file_info_new ();
2388 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2389 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2391 mime_type = gnome_vfs_file_info_get_mime_type (info);
2393 mime_part = tny_platform_factory_new_mime_part
2394 (modest_runtime_get_platform_factory ());
2396 TnyStream *stream = create_stream_for_uri (uri);
2398 if (stream == NULL) {
2400 modest_platform_information_banner (NULL, NULL,
2401 _FM("sfil_ib_opening_not_allowed"));
2403 g_object_unref (mime_part);
2404 gnome_vfs_file_info_unref (info);
2408 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2410 content_id = g_strdup_printf ("%d", priv->next_cid);
2411 tny_mime_part_set_content_id (mime_part, content_id);
2412 g_free (content_id);
2415 basename = g_path_get_basename (filename);
2416 tny_mime_part_set_filename (mime_part, basename);
2419 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2421 if (pixbuf != NULL) {
2422 priv->images_size += stream_size;
2423 priv->images_count ++;
2424 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2425 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2426 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2427 tny_mime_part_get_content_id (mime_part), pixbuf);
2428 g_object_unref (pixbuf);
2430 tny_list_prepend (priv->images, (GObject *) mime_part);
2431 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2433 modest_platform_information_banner (NULL, NULL,
2434 _("mail_ib_file_operation_failed"));
2438 g_object_unref (mime_part);
2439 gnome_vfs_file_info_unref (info);
2443 g_object_unref (window);
2447 on_attach_file_response (GtkDialog *dialog,
2451 GSList *uris = NULL;
2453 GnomeVFSFileSize total_size, allowed_size;
2454 ModestMsgEditWindow *window;
2455 ModestMsgEditWindowPrivate *priv;
2460 case GTK_RESPONSE_OK:
2462 gchar *current_folder;
2464 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2465 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2466 if (current_folder && current_folder != '\0') {
2468 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2469 current_folder, &err);
2471 g_debug ("Error storing latest used folder: %s", err->message);
2475 g_free (current_folder);
2482 window = MODEST_MSG_EDIT_WINDOW (user_data);
2483 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2485 /* allowed size is the maximum size - what's already there */
2486 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2487 &att_num, &att_size);
2488 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2491 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2493 const gchar *uri = (const gchar *) uri_node->data;
2496 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2498 if (total_size > allowed_size) {
2499 g_debug ("%s: total size: %u",
2500 __FUNCTION__, (unsigned int)total_size);
2503 allowed_size -= total_size;
2505 g_slist_foreach (uris, (GFunc) g_free, NULL);
2506 g_slist_free (uris);
2508 gtk_widget_destroy (GTK_WIDGET (dialog));
2512 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2514 GtkWidget *dialog = NULL;
2515 ModestMsgEditWindowPrivate *priv;
2518 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2520 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2522 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2525 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2526 GTK_FILE_CHOOSER_ACTION_OPEN);
2527 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2528 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2529 if (conf_folder && conf_folder[0] != '\0') {
2530 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2533 /* Set the default folder to images folder */
2534 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2535 ".documents", NULL);
2536 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2537 g_free (docs_folder);
2539 g_free (conf_folder);
2540 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2541 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2542 GTK_WINDOW (dialog), GTK_WINDOW (window));
2544 /* Connect to response & show */
2545 g_signal_connect (dialog, "response",
2546 G_CALLBACK (on_attach_file_response), window);
2547 gtk_widget_show (dialog);
2552 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2554 GnomeVFSFileSize allowed_size)
2557 GnomeVFSHandle *handle = NULL;
2558 ModestMsgEditWindowPrivate *priv;
2559 GnomeVFSResult result;
2560 GnomeVFSFileSize size = 0;
2561 g_return_val_if_fail (window, 0);
2562 g_return_val_if_fail (uri, 0);
2564 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2566 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2567 if (result == GNOME_VFS_OK) {
2568 TnyMimePart *mime_part;
2570 const gchar *mime_type = NULL;
2572 gchar *escaped_filename;
2575 GnomeVFSFileInfo *info;
2576 GnomeVFSURI *vfs_uri;
2578 gnome_vfs_close (handle);
2579 vfs_uri = gnome_vfs_uri_new (uri);
2582 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2583 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2584 g_free (escaped_filename);
2585 gnome_vfs_uri_unref (vfs_uri);
2587 info = gnome_vfs_file_info_new ();
2589 if (gnome_vfs_get_file_info (uri,
2591 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2593 mime_type = gnome_vfs_file_info_get_mime_type (info);
2594 mime_part = tny_platform_factory_new_mime_part
2595 (modest_runtime_get_platform_factory ());
2597 /* try to get the attachment's size; this may fail for weird
2598 * file systems, like obex, upnp... */
2599 if (allowed_size != 0 &&
2600 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2602 if (size > allowed_size) {
2603 modest_platform_information_banner (NULL, NULL,
2604 _("mail_ib_error_attachment_size"));
2609 g_debug ("%s: could not get attachment size", __FUNCTION__);
2611 stream = create_stream_for_uri (uri);
2613 if (stream == NULL) {
2615 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2617 g_object_unref (mime_part);
2619 gnome_vfs_file_info_unref (info);
2623 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2624 g_object_unref (stream);
2626 content_id = g_strdup_printf ("%d", priv->next_cid);
2627 tny_mime_part_set_content_id (mime_part, content_id);
2628 g_free (content_id);
2631 basename = g_path_get_basename (filename);
2632 tny_mime_part_set_filename (mime_part, basename);
2635 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2636 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2638 info->size == 0, info->size);
2639 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2640 gtk_widget_show_all (priv->attachments_caption);
2641 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2643 g_object_unref (mime_part);
2644 gnome_vfs_file_info_unref (info);
2651 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2654 ModestMsgEditWindowPrivate *priv;
2657 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2658 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2660 if (att_list == NULL) {
2661 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2662 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2663 g_object_unref (att_list);
2667 g_object_ref (att_list);
2670 if (tny_list_get_length (att_list) == 0) {
2671 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2673 gboolean dialog_response;
2674 gchar *message = NULL;
2675 gchar *filename = NULL;
2677 if (tny_list_get_length (att_list) == 1) {
2679 iter = tny_list_create_iterator (att_list);
2680 part = (TnyMimePart *) tny_iterator_get_current (iter);
2681 g_object_unref (iter);
2682 if (TNY_IS_MSG (part)) {
2683 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2685 filename = tny_header_dup_subject (header);
2686 g_object_unref (header);
2688 if (filename == NULL) {
2689 filename = g_strdup (_("mail_va_no_subject"));
2692 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2694 g_object_unref (part);
2696 filename = g_strdup ("");
2698 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2699 "emev_nc_delete_attachments",
2700 tny_list_get_length (att_list)), filename);
2703 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2707 if (dialog_response != GTK_RESPONSE_OK) {
2708 g_object_unref (att_list);
2712 for (iter = tny_list_create_iterator (att_list);
2713 !tny_iterator_is_done (iter);
2714 tny_iterator_next (iter)) {
2715 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2716 const gchar *att_id;
2717 tny_list_remove (priv->attachments, (GObject *) mime_part);
2719 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2721 if (tny_list_get_length (priv->attachments) == 0)
2722 gtk_widget_hide (priv->attachments_caption);
2723 att_id = tny_mime_part_get_content_id (mime_part);
2725 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2727 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2728 g_object_unref (mime_part);
2730 g_object_unref (iter);
2733 g_object_unref (att_list);
2735 /* if the last attachment has been removed, focus the Subject: field */
2736 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2737 gtk_widget_grab_focus (priv->subject_field);
2741 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2744 ModestMsgEditWindowPrivate *priv;
2745 GdkColor *new_color;
2746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2748 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2749 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2752 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2754 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2756 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2758 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2763 font_size_clicked (GtkToolButton *button,
2764 ModestMsgEditWindow *window)
2766 ModestMsgEditWindowPrivate *priv;
2767 GtkWidget *selector, *dialog;
2769 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2771 selector = hildon_touch_selector_new ();
2772 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2773 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2775 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2776 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2777 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2779 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2783 WPTextBufferFormat format;
2785 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2787 memset (&format, 0, sizeof (format));
2788 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2790 format.cs.font_size = TRUE;
2791 format.cs.text_position = TRUE;
2792 format.cs.font = TRUE;
2793 format.font_size = new_index;
2794 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2796 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2797 GINT_TO_POINTER (new_index)))
2798 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2800 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2801 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2802 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2803 size_text, "</span>", NULL);
2805 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2809 gtk_widget_destroy (dialog);
2811 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2816 font_face_clicked (GtkToolButton *button,
2817 ModestMsgEditWindow *window)
2819 ModestMsgEditWindowPrivate *priv;
2820 GtkWidget *selector, *dialog;
2821 GtkCellRenderer *renderer;
2823 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2825 selector = hildon_touch_selector_new ();
2826 renderer = gtk_cell_renderer_text_new ();
2827 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2828 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2829 renderer, "family", 0, "text", 0, NULL);
2830 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2832 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2833 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2834 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2836 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2837 gint new_font_index;
2841 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2842 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2843 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2847 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2849 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2850 GINT_TO_POINTER(new_font_index)))
2851 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2853 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2854 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2856 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2860 gtk_tree_path_free (path);
2863 gtk_widget_destroy (dialog);
2865 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2870 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2873 ModestMsgEditWindowPrivate *priv = NULL;
2874 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2876 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2877 if (!priv->update_caption_visibility)
2880 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2882 gtk_widget_show (priv->cc_caption);
2884 gtk_widget_hide (priv->cc_caption);
2886 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2890 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2893 ModestMsgEditWindowPrivate *priv = NULL;
2894 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2896 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2897 if (!priv->update_caption_visibility)
2900 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2902 gtk_widget_show (priv->bcc_caption);
2904 gtk_widget_hide (priv->bcc_caption);
2906 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2910 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2911 ModestRecptEditor *editor)
2913 ModestMsgEditWindowPrivate *priv;
2915 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2916 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2918 /* we check for low-mem; in that case, show a warning, and don't allow
2919 * for the addressbook
2921 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2924 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2926 if (editor == NULL) {
2927 GtkWidget *view_focus, *parent;
2928 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2930 /* This code should be kept in sync with ModestRecptEditor. The
2931 textview inside the recpt editor is the one that really gets the
2932 focus. As it's inside a scrolled window, and this one inside the
2933 hbox recpt editor inherits from, we'll need to go up in the
2934 hierarchy to know if the text view is part of the recpt editor
2935 or if it's a different text entry */
2936 parent = gtk_widget_get_parent (view_focus);
2937 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2938 editor = MODEST_RECPT_EDITOR (parent);
2941 editor = MODEST_RECPT_EDITOR (priv->to_field);
2944 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2948 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2950 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2952 modest_msg_edit_window_open_addressbook (window, NULL);
2956 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2957 gboolean show_toolbar)
2959 ModestWindowPrivate *parent_priv;
2960 ModestMsgEditWindowPrivate *priv;
2962 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2963 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2964 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2966 /* We can not just use the code of
2967 modest_msg_edit_window_setup_toolbar because it has a
2968 mixture of both initialization and creation code. */
2970 gint current_format;
2971 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2972 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2973 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2974 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2976 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2979 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2984 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2985 TnyHeaderFlags priority_flags)
2987 ModestMsgEditWindowPrivate *priv;
2988 ModestWindowPrivate *parent_priv;
2990 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2992 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2993 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2995 if (priv->priority_flags != priority_flags) {
2996 GtkAction *priority_action = NULL;
2998 priv->priority_flags = priority_flags;
3000 switch (priority_flags) {
3001 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3002 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3003 MODEST_HEADER_ICON_HIGH,
3004 HILDON_ICON_SIZE_SMALL);
3005 gtk_widget_show (priv->priority_icon);
3006 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3007 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3009 case TNY_HEADER_FLAG_LOW_PRIORITY:
3010 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3011 MODEST_HEADER_ICON_LOW,
3012 HILDON_ICON_SIZE_SMALL);
3013 gtk_widget_show (priv->priority_icon);
3014 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3015 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3018 gtk_widget_hide (priv->priority_icon);
3019 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3020 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3023 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3024 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3026 gtk_widget_queue_resize (priv->subject_box);
3030 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3033 ModestMsgEditWindowPrivate *priv;
3034 ModestWindowPrivate *parent_priv;
3035 gint current_format;
3037 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3039 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3040 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3042 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3043 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3045 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3047 if (parent_priv->toolbar) {
3048 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3049 gtk_widget_hide (parent_priv->toolbar);
3051 gtk_widget_show (parent_priv->toolbar);
3055 if (current_format != file_format) {
3056 switch (file_format) {
3057 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3058 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3059 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3061 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3065 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3066 response = gtk_dialog_run (GTK_DIALOG (dialog));
3067 gtk_widget_destroy (dialog);
3068 if (response == GTK_RESPONSE_OK) {
3069 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3070 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3072 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3073 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3078 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3079 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3080 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3085 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3088 ModestMsgEditWindowPrivate *priv;
3089 WPTextBufferFormat oldfmt, fmt;
3090 gint old_position = 0;
3094 GdkColor *color = NULL;
3095 gboolean bold, bold_set, italic, italic_set;
3096 gboolean underline, underline_set;
3097 gboolean strikethrough, strikethrough_set;
3098 gboolean position_set;
3099 gboolean font_size_set, font_set, color_set;
3102 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3103 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3105 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3106 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3107 GTK_WINDOW(dialog), GTK_WINDOW (window));
3109 /* First we get the currently selected font information */
3110 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3112 switch (oldfmt.text_position) {
3113 case TEXT_POSITION_NORMAL:
3116 case TEXT_POSITION_SUPERSCRIPT:
3124 g_object_set (G_OBJECT (dialog),
3125 "bold", oldfmt.bold != FALSE,
3126 "bold-set", !oldfmt.cs.bold,
3127 "underline", oldfmt.underline != FALSE,
3128 "underline-set", !oldfmt.cs.underline,
3129 "italic", oldfmt.italic != FALSE,
3130 "italic-set", !oldfmt.cs.italic,
3131 "strikethrough", oldfmt.strikethrough != FALSE,
3132 "strikethrough-set", !oldfmt.cs.strikethrough,
3133 "color", &oldfmt.color,
3134 "color-set", !oldfmt.cs.color,
3135 "size", wp_font_size[oldfmt.font_size],
3136 "size-set", !oldfmt.cs.font_size,
3137 "position", old_position,
3138 "position-set", !oldfmt.cs.text_position,
3139 "family", wp_get_font_name (oldfmt.font),
3140 "family-set", !oldfmt.cs.font,
3143 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3144 GTK_WINDOW (dialog), GTK_WINDOW (window));
3145 gtk_widget_show_all (dialog);
3146 priv->font_dialog = dialog;
3147 response = gtk_dialog_run (GTK_DIALOG (dialog));
3148 priv->font_dialog = NULL;
3149 if (response == GTK_RESPONSE_OK) {
3151 g_object_get( dialog,
3153 "bold-set", &bold_set,
3154 "underline", &underline,
3155 "underline-set", &underline_set,
3157 "italic-set", &italic_set,
3158 "strikethrough", &strikethrough,
3159 "strikethrough-set", &strikethrough_set,
3161 "color-set", &color_set,
3163 "size-set", &font_size_set,
3164 "family", &font_name,
3165 "family-set", &font_set,
3166 "position", &position,
3167 "position-set", &position_set,
3172 if (response == GTK_RESPONSE_OK) {
3173 memset(&fmt, 0, sizeof(fmt));
3179 fmt.italic = italic;
3180 fmt.cs.italic = TRUE;
3182 if (underline_set) {
3183 fmt.underline = underline;
3184 fmt.cs.underline = TRUE;
3186 if (strikethrough_set) {
3187 fmt.strikethrough = strikethrough;
3188 fmt.cs.strikethrough = TRUE;
3193 ? TEXT_POSITION_NORMAL
3194 : ( ( position == 1 )
3195 ? TEXT_POSITION_SUPERSCRIPT
3196 : TEXT_POSITION_SUBSCRIPT );
3197 fmt.cs.text_position = TRUE;
3198 fmt.font_size = oldfmt.font_size;
3202 fmt.cs.color = TRUE;
3205 fmt.font = wp_get_font_index(font_name,
3210 if (font_size_set) {
3211 fmt.cs.font_size = TRUE;
3212 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3214 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3215 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3217 gtk_widget_destroy (dialog);
3219 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3223 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3225 ModestMsgEditWindowPrivate *priv;
3227 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3228 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3230 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3232 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3233 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3237 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3239 ModestMsgEditWindowPrivate *priv;
3241 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3242 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3244 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3246 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3247 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3252 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3254 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 priv->can_undo = can_undo;
3260 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3262 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3264 priv->can_redo = can_redo;
3268 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3270 ModestMsgEditWindowPrivate *priv;
3271 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3272 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3274 return priv->can_undo;
3278 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3280 ModestMsgEditWindowPrivate *priv;
3281 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3282 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3284 return priv->can_redo;
3289 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3292 GtkTextIter match_start, match_end;
3294 if (image_id == NULL)
3297 gtk_text_buffer_get_start_iter (buffer, &iter);
3299 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3300 GSList *tags = gtk_text_iter_get_tags (&match_start);
3302 for (node = tags; node != NULL; node = g_slist_next (node)) {
3303 GtkTextTag *tag = (GtkTextTag *) node->data;
3304 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3305 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3306 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3308 offset = gtk_text_iter_get_offset (&match_start);
3309 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3310 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3314 gtk_text_iter_forward_char (&iter);
3319 message_is_empty (ModestMsgEditWindow *window)
3321 ModestMsgEditWindowPrivate *priv = NULL;
3323 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3326 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3327 * so we can ignore markup.
3329 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3332 count = gtk_text_buffer_get_char_count (buf);
3338 msg_body_focus (GtkWidget *focus,
3339 GdkEventFocus *event,
3343 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3344 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3345 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3350 recpt_field_changed (GtkTextBuffer *buffer,
3351 ModestMsgEditWindow *editor)
3353 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3354 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3358 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3360 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3361 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3365 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3368 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3369 GtkTextBuffer *buffer;
3371 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3372 gtk_text_buffer_set_modified (buffer, modified);
3373 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3374 gtk_text_buffer_set_modified (buffer, modified);
3375 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3376 gtk_text_buffer_set_modified (buffer, modified);
3377 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3381 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3383 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3384 const char *account_name;
3385 GtkTextBuffer *buffer;
3387 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3388 if (gtk_text_buffer_get_modified (buffer))
3390 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3391 if (gtk_text_buffer_get_modified (buffer))
3393 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3394 if (gtk_text_buffer_get_modified (buffer))
3396 if (gtk_text_buffer_get_modified (priv->text_buffer))
3399 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3400 if (priv->original_mailbox) {
3401 if (!account_name || strcmp (account_name, priv->original_mailbox))
3403 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3414 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3416 ModestMsgEditWindowPrivate *priv = NULL;
3418 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3419 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3421 /* check if there's no recipient added */
3422 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3423 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3424 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3425 /* no recipient contents, then select contacts */
3426 modest_msg_edit_window_open_addressbook (window, NULL);
3430 g_object_ref (window);
3431 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3432 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3433 g_object_unref (window);
3436 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3437 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3438 g_object_unref (window);
3441 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3442 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3443 g_object_unref (window);
3447 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3448 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3449 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3450 g_object_unref (window);
3457 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3458 ModestMsgEditWindow *window)
3460 modest_msg_edit_window_offer_attach_file (window);
3464 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3466 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3468 return priv->clipboard_text;
3472 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3474 ModestMsgEditWindow *window)
3476 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3477 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3480 /* It could happen that the window was already closed */
3481 if (!GTK_WIDGET_VISIBLE (window))
3484 g_object_ref (window);
3485 text = gtk_clipboard_wait_for_text (selection_clipboard);
3487 if (priv->clipboard_text != NULL) {
3488 g_free (priv->clipboard_text);
3490 priv->clipboard_text = text;
3492 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3494 g_object_unref (window);
3497 static gboolean clipboard_owner_change_idle (gpointer userdata)
3499 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3500 ModestMsgEditWindowPrivate *priv;
3502 gdk_threads_enter ();
3503 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3504 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3506 priv->clipboard_owner_idle = 0;
3507 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3508 gdk_threads_leave ();
3514 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3516 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3517 if (priv->clipboard_owner_idle == 0) {
3518 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3519 clipboard_owner_change_idle,
3520 g_object_ref (window),
3526 subject_field_move_cursor (GtkEntry *entry,
3527 GtkMovementStep step,
3532 /* It could happen that the window was already closed */
3533 if (!GTK_WIDGET_VISIBLE (window))
3536 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3540 update_window_title (ModestMsgEditWindow *window)
3542 ModestMsgEditWindowPrivate *priv = NULL;
3543 const gchar *subject;
3545 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3546 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3547 if (subject == NULL || subject[0] == '\0')
3548 subject = _("mail_va_new_email");
3550 gtk_window_set_title (GTK_WINDOW (window), subject);
3556 body_insert_text (GtkTextBuffer *buffer,
3557 GtkTextIter *location,
3560 ModestMsgEditWindow *window)
3562 GtkTextIter end_iter;
3566 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3568 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3570 offset = gtk_text_iter_get_offset (&end_iter);
3571 utf8_len = g_utf8_strlen (text, len);
3573 if (offset + utf8_len > MAX_BODY_LENGTH) {
3574 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3575 if (offset < MAX_BODY_LENGTH)
3580 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3582 /* Prevent endless recursion */
3583 result = g_strndup (text, utf8_end - text);
3584 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3585 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3586 (gpointer) result, (gpointer) (utf8_end - text),
3588 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3592 if (offset + utf8_len > MAX_BODY_LENGTH) {
3593 if (priv->max_chars_banner == NULL) {
3594 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3595 _CS("ckdg_ib_maximum_characters_reached"));
3596 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3602 subject_field_changed (GtkEditable *editable,
3603 ModestMsgEditWindow *window)
3605 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3606 update_window_title (window);
3607 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3608 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3609 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3612 subject_field_insert_text (GtkEditable *editable,
3614 gint new_text_length,
3616 ModestMsgEditWindow *window)
3618 GString *result = g_string_new ("");
3620 gint result_len = 0;
3621 const gchar *entry_text = NULL;
3624 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3625 old_length = g_utf8_strlen (entry_text, -1);
3627 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3628 gunichar c = g_utf8_get_char_validated (current, 8);
3629 /* Invalid unichar, stop */
3635 result = g_string_append_unichar (result, c);
3639 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3640 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3643 /* Prevent endless recursion */
3644 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3645 g_signal_emit_by_name (editable, "insert-text",
3646 (gpointer) result->str, (gpointer) result->len,
3647 (gpointer) position, (gpointer) window);
3648 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3652 if (result_len + old_length > 1000) {
3653 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3654 _CS("ckdg_ib_maximum_characters_reached"));
3656 g_string_free (result, TRUE);
3660 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3663 ModestMsgEditWindowPrivate *priv = NULL;
3665 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3666 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3668 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3671 gtk_widget_show_all (priv->find_toolbar);
3672 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3674 gtk_widget_hide_all (priv->find_toolbar);
3675 gtk_widget_grab_focus (priv->msg_body);
3680 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3682 GtkTextIter *match_start,
3683 GtkTextIter *match_end)
3685 GtkTextIter end_iter;
3686 gchar *str_casefold;
3689 gchar *range_casefold;
3692 gboolean result = FALSE;
3699 gtk_text_iter_forward_to_end (&end_iter);
3701 str_casefold = g_utf8_casefold (str, -1);
3702 str_chars_n = strlen (str);
3704 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3705 range_casefold = g_utf8_casefold (range_text, -1);
3706 range_chars_n = strlen (range_casefold);
3708 if (range_chars_n < str_chars_n) {
3709 g_free (str_casefold);
3710 g_free (range_text);
3711 g_free (range_casefold);
3715 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3716 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3717 if (!g_utf8_collate (range_subtext, str_casefold)) {
3718 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3720 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3721 match_start, match_end, NULL)) {
3722 g_debug ("Matched string with collate, but not matched in model");
3724 g_free (found_text);
3726 g_free (range_subtext);
3730 g_free (str_casefold);
3731 g_free (range_text);
3732 g_free (range_casefold);
3739 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3740 ModestMsgEditWindow *window)
3742 gchar *current_search = NULL;
3743 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3745 GtkTextIter selection_start, selection_end;
3746 GtkTextIter match_start, match_end;
3747 gboolean continue_search = FALSE;
3749 if (message_is_empty (window)) {
3750 g_free (priv->last_search);
3751 priv->last_search = NULL;
3752 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3756 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3757 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3758 g_free (current_search);
3759 g_free (priv->last_search);
3760 priv->last_search = NULL;
3761 /* Information banner about empty search */
3762 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3766 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3767 continue_search = TRUE;
3769 g_free (priv->last_search);
3770 priv->last_search = g_strdup (current_search);
3773 if (continue_search) {
3774 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3775 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3776 &match_start, &match_end);
3778 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3780 GtkTextIter buffer_start;
3781 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3782 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3783 &match_start, &match_end);
3785 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3788 /* Mark as selected the string found in search */
3790 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3791 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3792 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3794 g_free (priv->last_search);
3795 priv->last_search = NULL;
3797 g_free (current_search);
3801 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3803 ModestMsgEditWindowPrivate *priv;
3805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3810 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3813 ModestMsgEditWindowPrivate *priv;
3815 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3820 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3821 ModestMsgEditWindow *window)
3823 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3827 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3830 ModestMsgEditWindowPrivate *priv;
3831 TnyHeader *header = NULL;
3833 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3834 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3836 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3838 if (priv->draft_msg != NULL) {
3839 g_object_unref (priv->draft_msg);
3842 if (draft != NULL) {
3843 g_object_ref (draft);
3844 header = tny_msg_get_header (draft);
3845 if (priv->msg_uid) {
3846 g_free (priv->msg_uid);
3847 priv->msg_uid = NULL;
3849 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3852 priv->draft_msg = draft;
3856 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3857 GtkTextIter *start, GtkTextIter *end,
3860 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3861 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3864 if (tag == NULL) return;
3865 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3866 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3867 replace_with_images (window, priv->images);
3872 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3875 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3877 g_return_if_fail (TNY_IS_MIME_PART (part));
3878 tny_list_prepend (priv->attachments, (GObject *) part);
3879 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3880 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3881 gtk_widget_show_all (priv->attachments_caption);
3882 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3886 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3888 ModestMsgEditWindowPrivate *priv;
3890 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3891 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3893 return priv->msg_uid;
3897 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3898 ModestMsgEditWindowWidgetType widget_type)
3900 ModestMsgEditWindowPrivate *priv;
3902 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3903 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3905 switch (widget_type) {
3906 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3907 return priv->msg_body;
3909 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3910 return priv->to_field;
3912 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3913 return priv->cc_field;
3915 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3916 return priv->bcc_field;
3918 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3919 return priv->subject_field;
3921 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3922 return priv->attachments_view;
3930 remove_tags (WPTextBuffer *buffer)
3932 GtkTextIter start, end;
3934 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3935 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3937 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3941 on_account_removed (TnyAccountStore *account_store,
3942 TnyAccount *account,
3945 /* Do nothing if it's a store account, because we use the
3946 transport to send the messages */
3947 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3948 const gchar *parent_acc = NULL;
3949 const gchar *our_acc = NULL;
3951 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3952 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3953 /* Close this window if I'm showing a message of the removed account */
3954 if (strcmp (parent_acc, our_acc) == 0)
3955 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3959 static void update_signature (ModestMsgEditWindow *self,
3960 const gchar *old_account,
3961 const gchar *new_account)
3963 ModestMsgEditWindowPrivate *priv;
3964 gboolean has_old_signature, has_new_signature;
3966 GtkTextIter match_start, match_end;
3967 ModestAccountMgr *mgr;
3969 gchar *full_signature;
3971 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3973 gtk_text_buffer_begin_user_action (priv->text_buffer);
3975 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3976 mgr = modest_runtime_get_account_mgr ();
3980 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3981 if (has_old_signature) {
3982 full_signature = g_strconcat ("\n--\n", signature, NULL);
3983 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3984 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3986 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3987 &match_start, &match_end, NULL)) {
3990 g_free (full_signature);
3995 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3996 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3997 if (has_new_signature) {
3998 full_signature = g_strconcat ("\n--\n", signature, NULL);
3999 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4000 g_free (full_signature);
4003 gtk_text_buffer_end_user_action (priv->text_buffer);
4006 static void update_branding (ModestMsgEditWindow *self,
4007 const gchar *new_account)
4009 ModestMsgEditWindowPrivate *priv;
4010 ModestAccountMgr *mgr;
4011 const GdkPixbuf *new_icon = NULL;
4012 gchar *new_label = NULL;
4014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4016 mgr = modest_runtime_get_account_mgr ();
4018 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4020 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4021 gtk_widget_show (priv->brand_icon);
4023 gtk_widget_hide (priv->brand_icon);
4026 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4027 gtk_widget_show (priv->brand_label);
4030 gtk_widget_hide (priv->brand_label);
4035 from_field_changed (HildonPickerButton *button,
4036 ModestMsgEditWindow *self)
4038 ModestMsgEditWindowPrivate *priv;
4039 gchar *old_account, *new_account;
4041 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4043 old_account = priv->last_from_account;
4044 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4045 new_account = priv->last_from_account;
4047 update_signature (self, old_account, new_account);
4048 update_branding (self, new_account);
4052 typedef struct _MessageSettingsHelper {
4053 ModestMsgEditWindow *window;
4054 GSList *priority_group;
4055 GSList *format_group;
4056 GtkToggleButton *current_priority;
4057 GtkToggleButton *current_format;
4058 } MessageSettingsHelper;
4061 on_priority_toggle (GtkToggleButton *button,
4062 MessageSettingsHelper *helper)
4065 ModestMsgEditWindowPrivate *priv;
4067 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4068 if (gtk_toggle_button_get_active (button)) {
4070 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4071 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4072 if ((node_button != button) &&
4073 gtk_toggle_button_get_active (node_button)) {
4074 gtk_toggle_button_set_active (node_button, FALSE);
4077 helper->current_priority = button;
4079 gboolean found = FALSE;
4080 /* If no one is active, activate it again */
4081 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4082 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4083 if (gtk_toggle_button_get_active (node_button)) {
4089 gtk_toggle_button_set_active (button, TRUE);
4095 on_format_toggle (GtkToggleButton *button,
4096 MessageSettingsHelper *helper)
4099 ModestMsgEditWindowPrivate *priv;
4101 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4102 if (gtk_toggle_button_get_active (button)) {
4104 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4105 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4106 if ((node_button != button) &&
4107 gtk_toggle_button_get_active (node_button)) {
4108 gtk_toggle_button_set_active (node_button, FALSE);
4111 helper->current_format = button;
4113 gboolean found = FALSE;
4114 /* If no one is active, activate it again */
4115 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4116 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4117 if (gtk_toggle_button_get_active (node_button)) {
4123 gtk_toggle_button_set_active (button, TRUE);
4130 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4135 GtkWidget *priority_hbox;
4136 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4137 GtkWidget *captioned;
4138 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4139 GtkWidget *format_hbox;
4140 GtkWidget *html_toggle, *text_toggle;
4141 ModestMsgEditWindowPrivate *priv;
4142 MessageSettingsHelper helper = {0,};
4144 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4145 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4146 helper.window = window;
4147 helper.priority_group = NULL;
4148 helper.format_group = NULL;
4150 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4151 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4153 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4154 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4155 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4156 vbox = gtk_vbox_new (FALSE, 0);
4157 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4158 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4159 gtk_container_add (GTK_CONTAINER (align), vbox);
4160 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4161 gtk_widget_show (align);
4162 gtk_widget_show (vbox);
4164 /* Priority toggles */
4165 priority_hbox = gtk_hbox_new (TRUE, 0);
4166 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4167 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4168 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4169 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4170 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4171 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4172 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4173 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4174 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4175 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4176 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4177 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4178 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4179 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4180 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4181 gtk_widget_show_all (priority_hbox);
4182 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4183 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4184 gtk_widget_show (captioned);
4185 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4187 /* format toggles */
4188 format_hbox = gtk_hbox_new (TRUE, 0);
4189 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4190 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4191 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4192 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4193 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4194 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4195 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4196 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4197 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4198 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4199 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4200 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4201 gtk_widget_show_all (format_hbox);
4202 gtk_widget_show (format_hbox);
4203 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4206 g_object_unref (title_sizegroup);
4207 g_object_unref (value_sizegroup);
4209 /* Set current values */
4210 switch (priv->priority_flags) {
4211 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4212 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4213 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4215 case TNY_HEADER_FLAG_LOW_PRIORITY:
4216 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4217 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4220 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4221 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4225 switch (modest_msg_edit_window_get_format (window)) {
4226 case MODEST_MSG_EDIT_FORMAT_TEXT:
4227 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4228 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4230 case MODEST_MSG_EDIT_FORMAT_HTML:
4232 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4233 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4237 /* Signal connects */
4238 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4239 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4240 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4241 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4242 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4244 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4245 GTK_WINDOW (dialog), GTK_WINDOW (window));
4247 /* Save settings if the user clicked on done */
4248 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4249 TnyHeaderFlags flags;
4250 ModestMsgEditFormat old_format, new_format;
4252 /* Set priority flags */
4253 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4254 if (priv->priority_flags != flags)
4255 modest_msg_edit_window_set_priority_flags (window, flags);
4257 /* Set edit format */
4258 old_format = modest_msg_edit_window_get_format (window);
4259 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4260 if (old_format != new_format) {
4261 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4262 modest_msg_edit_window_set_file_format (window, file_format);
4266 gtk_widget_destroy (dialog);
4267 g_slist_free (helper.priority_group);
4271 on_message_settings (GtkAction *action,
4272 ModestMsgEditWindow *window)
4274 modest_msg_edit_window_show_msg_settings_dialog (window);
4278 on_cc_button_toggled (HildonCheckButton *button,
4279 ModestMsgEditWindow *window)
4281 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4283 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4284 hildon_check_button_get_active (button));
4288 on_bcc_button_toggled (HildonCheckButton *button,
4289 ModestMsgEditWindow *window)
4291 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4293 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4294 hildon_check_button_get_active (button));
4298 setup_menu (ModestMsgEditWindow *self)
4300 ModestMsgEditWindowPrivate *priv = NULL;
4302 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4304 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4306 /* Settings menu buttons */
4307 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4308 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4310 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4311 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4312 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4314 priv->cc_button = hildon_check_button_new (0);
4315 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4316 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4318 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4320 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4321 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4322 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4323 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4325 priv->bcc_button = hildon_check_button_new (0);
4326 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4327 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4329 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4331 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4332 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4333 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4334 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4336 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4337 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4338 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4339 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4340 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4342 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4343 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4344 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4345 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4346 APP_MENU_CALLBACK (on_message_settings),
4348 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4349 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4354 emit_open_addressbook (GtkButton *button,
4355 ModestRecptEditor *editor)
4357 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4361 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4362 const gchar *label, GtkWidget *control)
4364 GtkWidget *abook_button;
4367 GtkWidget *label_widget;
4369 box = gtk_hbox_new (FALSE, 0);
4371 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4372 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4374 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4375 label_widget = gtk_label_new (label);
4376 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4377 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4379 gtk_container_add (GTK_CONTAINER (align), abook_button);
4380 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4381 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4382 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4383 if (title_size_group)
4384 gtk_size_group_add_widget (title_size_group, label_widget);
4385 if (value_size_group)
4386 gtk_size_group_add_widget (value_size_group, control);
4388 g_signal_connect (G_OBJECT (abook_button), "clicked",
4389 G_CALLBACK (emit_open_addressbook), control);
4395 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4397 ModestMsgEditWindowPrivate *priv = NULL;
4399 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4402 priv->max_chars_banner = NULL;