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->faces_model);
1102 g_object_unref (priv->sizes_model);
1103 g_object_unref (priv->attachments);
1104 g_object_unref (priv->images);
1106 /* This had to stay alive for as long as the picker that used it: */
1107 modest_pair_list_free (priv->from_field_protos);
1109 G_OBJECT_CLASS(parent_class)->finalize (obj);
1113 pixbuf_size_prepared (GdkPixbufLoader *loader,
1116 ModestMsgEditWindow *self)
1118 gint new_height, new_width;
1121 new_height = height;
1125 if (width > IMAGE_MAX_WIDTH) {
1126 new_height = height * IMAGE_MAX_WIDTH / width;
1127 new_width = IMAGE_MAX_WIDTH;
1130 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1134 pixbuf_from_stream (TnyStream *stream,
1135 const gchar *mime_type,
1136 guint64 *stream_size,
1137 ModestMsgEditWindow *self)
1139 GdkPixbufLoader *loader;
1142 GError *error = NULL;
1146 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1148 if (loader == NULL) {
1153 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1155 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1157 tny_stream_reset (TNY_STREAM (stream));
1158 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1159 unsigned char read_buffer[128];
1161 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1163 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1166 /* Allow some UI responsiveness */
1167 while (gtk_events_pending ())
1168 gtk_main_iteration ();
1170 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1172 gdk_pixbuf_loader_close (loader, &error);
1175 g_error_free (error);
1176 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1178 g_object_ref (pixbuf);
1179 g_object_unref (loader);
1184 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1185 GdkPixbuf *new_pixbuf;
1187 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1188 gdk_pixbuf_get_width (pixbuf);
1189 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1190 g_object_unref (pixbuf);
1191 pixbuf = new_pixbuf;
1195 *stream_size = size;
1201 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1203 ModestMsgEditWindowPrivate *priv;
1206 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1208 g_object_ref (self);
1209 for (iter = tny_list_create_iterator (attachments);
1210 !tny_iterator_is_done (iter);
1211 tny_iterator_next (iter)) {
1212 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1213 const gchar *cid = tny_mime_part_get_content_id (part);
1214 const gchar *mime_type = tny_mime_part_get_content_type (part);
1215 if ((cid != NULL)&&(mime_type != NULL)) {
1216 guint64 stream_size;
1217 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1218 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1221 g_object_unref (stream);
1223 if (pixbuf != NULL) {
1224 priv->images_count ++;
1225 priv->images_size += stream_size;
1226 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1227 g_object_unref (pixbuf);
1230 g_object_unref (part);
1232 g_object_unref (iter);
1233 g_object_unref (self);
1237 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1239 TnyMimePart *parent = NULL;
1240 const gchar *content_type = NULL;
1241 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1243 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1245 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1246 parent = g_object_ref (msg);
1247 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1248 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1251 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1252 iter = tny_list_create_iterator (parts);
1253 while (!tny_iterator_is_done (iter)) {
1255 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1256 content_type = tny_mime_part_get_content_type (part);
1257 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1261 g_object_unref (part);
1263 tny_iterator_next (iter);
1265 g_object_unref (iter);
1266 g_object_unref (parts);
1269 if (parent != NULL) {
1270 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1273 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1274 iter = tny_list_create_iterator (parts);
1275 while (!tny_iterator_is_done (iter)) {
1277 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1278 content_type = tny_mime_part_get_content_type (part);
1279 if (content_type && g_str_has_prefix (content_type, "image/")) {
1280 tny_list_prepend (priv->images, (GObject *) part);
1282 g_object_unref (part);
1283 tny_iterator_next (iter);
1285 g_object_unref (iter);
1286 g_object_unref (parts);
1287 g_object_unref (parent);
1292 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1295 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1297 for (iter = tny_list_create_iterator (attachments) ;
1298 !tny_iterator_is_done (iter);
1299 tny_iterator_next (iter)) {
1300 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1301 const gchar *cid = tny_mime_part_get_content_id (part);
1303 char *invalid = NULL;
1304 gint int_cid = strtol (cid, &invalid, 10);
1305 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1306 priv->next_cid = int_cid + 1;
1309 g_object_unref (part);
1311 g_object_unref (iter);
1315 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1318 gchar *to, *cc, *bcc, *subject;
1320 ModestMsgEditWindowPrivate *priv;
1321 ModestWindowPrivate *parent_priv;
1323 TnyHeaderFlags priority_flags;
1324 TnyFolder *msg_folder;
1325 gboolean is_html = FALSE;
1326 gboolean field_view_set;
1328 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1329 g_return_if_fail (TNY_IS_MSG (msg));
1331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1332 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1334 header = tny_msg_get_header (msg);
1335 to = tny_header_dup_to (header);
1336 cc = tny_header_dup_cc (header);
1337 bcc = tny_header_dup_bcc (header);
1338 subject = tny_header_dup_subject (header);
1340 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1341 priority_flags = tny_header_get_priority (header);
1344 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1346 field_view_set = TRUE;
1348 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1349 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1350 gtk_widget_show (priv->cc_caption);
1351 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1352 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1353 gtk_widget_hide (priv->cc_caption);
1354 field_view_set = FALSE;
1356 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1358 field_view_set = TRUE;
1360 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1361 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1362 gtk_widget_show (priv->bcc_caption);
1363 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1364 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1365 gtk_widget_hide (priv->bcc_caption);
1366 field_view_set = FALSE;
1368 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1372 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1373 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1376 update_window_title (self);
1378 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1379 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1381 if ((body == NULL)||(body[0] == '\0')) {
1383 body = modest_text_utils_convert_to_html ("");
1386 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1387 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1390 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1393 /* Add attachments to the view */
1394 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1395 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1396 if (tny_list_get_length (priv->attachments) == 0) {
1397 gtk_widget_hide (priv->attachments_caption);
1399 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1400 gtk_widget_show_all (priv->attachments_caption);
1402 get_related_images (self, msg);
1403 update_next_cid (self, priv->attachments);
1404 update_next_cid (self, priv->images);
1405 replace_with_images (self, priv->images);
1407 if (preserve_is_rich && !is_html) {
1408 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1409 /* Get the default format required from configuration */
1410 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1411 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1414 /* Set the default focus depending on having already a To: field or not */
1415 if ((!to)||(*to == '\0')) {
1416 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1418 gtk_widget_grab_focus (priv->msg_body);
1421 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1423 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1424 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1426 modest_msg_edit_window_set_modified (self, FALSE);
1428 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1429 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1430 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1431 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1433 if (priv->msg_uid) {
1434 g_free (priv->msg_uid);
1435 priv->msg_uid = NULL;
1438 /* we should set a reference to the incoming message if it is a draft */
1439 msg_folder = tny_msg_get_folder (msg);
1441 if (modest_tny_folder_is_local_folder (msg_folder)) {
1442 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1443 if (type == TNY_FOLDER_TYPE_INVALID)
1444 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1446 if (type == TNY_FOLDER_TYPE_DRAFTS)
1447 priv->draft_msg = g_object_ref(msg);
1448 if (type == TNY_FOLDER_TYPE_OUTBOX)
1449 priv->outbox_msg = g_object_ref(msg);
1450 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1452 g_object_unref (msg_folder);
1463 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1465 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1466 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1467 GtkWidget *placeholder;
1468 GtkWidget *tool_item;
1473 GtkWidget *sizes_menu;
1474 GtkWidget *fonts_menu;
1480 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1481 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1482 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1483 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1485 /* Font color placeholder */
1486 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1487 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1490 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1491 priv->font_color_button = hildon_color_button_new ();
1492 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1493 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1494 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1495 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1496 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1497 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1498 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1499 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1501 G_CALLBACK (modest_msg_edit_window_color_button_change),
1504 /* Font size and face placeholder */
1505 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1506 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1508 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1509 priv->size_tool_button_label = gtk_label_new (NULL);
1510 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1511 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1512 size_text, "</span>", NULL);
1513 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1514 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1516 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1517 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1518 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1519 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1520 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1521 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1522 gtk_widget_set_sensitive (arrow, FALSE);
1523 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1524 sizes_menu = gtk_menu_new ();
1525 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1526 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1529 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1530 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1532 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1536 if (wp_font_size[size_index] == 12)
1537 priv->current_size_index = size_index;
1541 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1542 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1543 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1544 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1545 priv->font_size_toolitem = tool_item;
1548 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1549 priv->font_tool_button_label = gtk_label_new (NULL);
1550 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1551 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1552 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1554 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1555 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1556 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1557 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1558 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1559 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1560 gtk_widget_set_sensitive (arrow, FALSE);
1561 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1562 fonts_menu = gtk_menu_new ();
1563 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1564 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1567 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1569 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1570 0, wp_get_font_name (font_index),
1573 if (font_index == DEFAULT_FONT)
1574 priv->current_face_index = font_index;
1576 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1577 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1578 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1579 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1580 priv->font_face_toolitem = tool_item;
1582 /* Set expand and homogeneous for remaining items */
1583 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1584 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1585 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1586 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1587 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1588 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1590 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1591 will not show the tool items added to the placeholders) */
1592 gtk_widget_show_all (parent_priv->toolbar);
1594 /* Set the no show all *after* showing all items. We do not
1595 want the toolbar to be shown with a show all because it
1596 could go agains the gconf setting regarding showing or not
1597 the toolbar of the editor window */
1598 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1604 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1607 ModestWindowPrivate *parent_priv;
1608 ModestMsgEditWindowPrivate *priv;
1609 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1610 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1611 ModestWindowMgr *mgr = NULL;
1613 g_return_val_if_fail (msg, NULL);
1614 g_return_val_if_fail (account_name, NULL);
1616 mgr = modest_runtime_get_window_mgr ();
1618 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1620 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1621 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1623 /* Menubar. Update the state of some toggles */
1624 priv->from_field_protos = get_transports ();
1625 priv->original_mailbox = NULL;
1626 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1627 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1628 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1629 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1630 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1631 priv->original_mailbox = g_strdup (mailbox);
1632 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1633 /* We set the first mailbox as the active mailbox */
1634 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1635 if (priv->original_mailbox != NULL)
1636 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1637 (gpointer) priv->original_mailbox);
1639 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1640 (gpointer) account_name);
1642 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1644 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1645 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1646 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1648 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1649 hildon_touch_selector_get_current_text
1650 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1651 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1652 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1655 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1657 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1659 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1660 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1662 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1664 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1665 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1666 /* Add common dimming rules */
1667 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1668 modest_msg_edit_window_toolbar_dimming_entries,
1669 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1670 MODEST_WINDOW (obj));
1671 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1672 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1673 MODEST_WINDOW (obj));
1674 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1675 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1676 MODEST_WINDOW (obj));
1677 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1678 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1679 MODEST_WINDOW (obj));
1680 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1681 G_CALLBACK (modest_ui_dimming_rules_on_send),
1682 MODEST_WINDOW (obj));
1683 /* Insert dimming rules group for this window */
1684 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1685 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1687 /* Setup app menu */
1688 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1690 /* Checks the dimming rules */
1691 g_object_unref (toolbar_rules_group);
1692 g_object_unref (clipboard_rules_group);
1693 gtk_widget_hide (priv->priority_icon);
1694 gtk_widget_queue_resize (priv->subject_box);
1695 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1697 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1699 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1700 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1701 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1702 priv->update_caption_visibility = TRUE;
1704 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1706 /* Track account-removed signal, this window should be closed
1707 in the case we're creating a mail associated to the account
1709 priv->account_removed_handler_id =
1710 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1712 G_CALLBACK(on_account_removed),
1715 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1717 return (ModestWindow*) obj;
1721 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1723 GString **string_buffer = (GString **) user_data;
1725 *string_buffer = g_string_append (*string_buffer, buffer);
1731 * @result: A new string which should be freed with g_free().
1734 get_formatted_data (ModestMsgEditWindow *edit_window)
1736 ModestMsgEditWindowPrivate *priv;
1737 GString *string_buffer = g_string_new ("");
1739 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1741 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1743 modest_text_utils_hyperlinkify (string_buffer);
1745 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1747 return g_string_free (string_buffer, FALSE);
1752 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1755 const gchar *account_name;
1756 ModestMsgEditWindowPrivate *priv;
1757 TnyIterator *att_iter;
1758 const gchar *picker_active_id;
1760 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1762 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1764 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1765 g_return_val_if_fail (picker_active_id, NULL);
1766 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1768 /* don't free these (except from) */
1769 data = g_slice_new0 (MsgData);
1770 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1771 data->account_name = g_strdup (account_name);
1772 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1773 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1774 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1775 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1776 data->references = g_strdup (priv->references);
1777 data->in_reply_to = g_strdup (priv->in_reply_to);
1778 if (priv->draft_msg) {
1779 data->draft_msg = g_object_ref (priv->draft_msg);
1780 } else if (priv->outbox_msg) {
1781 data->draft_msg = g_object_ref (priv->outbox_msg);
1783 data->draft_msg = NULL;
1786 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1788 gtk_text_buffer_get_bounds (buf, &b, &e);
1789 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1791 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1792 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1794 data->html_body = NULL;
1796 /* deep-copy the data */
1797 att_iter = tny_list_create_iterator (priv->attachments);
1798 data->attachments = NULL;
1799 while (!tny_iterator_is_done (att_iter)) {
1800 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1801 if (!(TNY_IS_MIME_PART(part))) {
1802 g_warning ("strange data in attachment list");
1803 g_object_unref (part);
1804 tny_iterator_next (att_iter);
1807 data->attachments = g_list_append (data->attachments,
1809 tny_iterator_next (att_iter);
1811 g_object_unref (att_iter);
1813 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1814 att_iter = tny_list_create_iterator (priv->images);
1815 data->images = NULL;
1816 while (!tny_iterator_is_done (att_iter)) {
1817 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1819 if (!(TNY_IS_MIME_PART(part))) {
1820 g_warning ("strange data in attachment list");
1821 g_object_unref (part);
1822 tny_iterator_next (att_iter);
1825 cid = tny_mime_part_get_content_id (part);
1827 gchar *image_tag_id;
1828 GtkTextTag *image_tag;
1830 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1831 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1832 g_free (image_tag_id);
1834 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1836 ((gtk_text_iter_has_tag (&iter, image_tag))||
1837 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1838 data->images = g_list_append (data->images,
1839 g_object_ref (part));
1841 g_object_unref (part);
1842 tny_iterator_next (att_iter);
1844 g_object_unref (att_iter);
1846 data->priority_flags = priv->priority_flags;
1853 unref_gobject (GObject *obj, gpointer data)
1855 if (!G_IS_OBJECT(obj))
1857 g_object_unref (obj);
1861 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1864 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1872 g_free (data->from);
1873 g_free (data->subject);
1874 g_free (data->plain_body);
1875 g_free (data->html_body);
1876 g_free (data->account_name);
1877 g_free (data->references);
1878 g_free (data->in_reply_to);
1880 if (data->draft_msg != NULL) {
1881 g_object_unref (data->draft_msg);
1882 data->draft_msg = NULL;
1885 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1886 g_list_free (data->attachments);
1887 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1888 g_list_free (data->images);
1890 g_slice_free (MsgData, data);
1894 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1896 guint64 *parts_size)
1898 ModestMsgEditWindowPrivate *priv;
1900 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1902 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1904 /* TODO: add images */
1905 *parts_size += priv->images_size;
1906 *parts_count += priv->images_count;
1911 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1914 ModestMsgEditWindowPrivate *priv = NULL;
1915 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1917 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1919 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1921 return MODEST_MSG_EDIT_FORMAT_HTML;
1923 return MODEST_MSG_EDIT_FORMAT_TEXT;
1927 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1928 ModestMsgEditFormat format)
1930 ModestMsgEditWindowPrivate *priv;
1931 ModestWindowPrivate *parent_priv;
1933 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1935 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1938 case MODEST_MSG_EDIT_FORMAT_HTML:
1939 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1940 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1942 case MODEST_MSG_EDIT_FORMAT_TEXT:
1943 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1944 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1947 g_return_if_reached ();
1951 ModestMsgEditFormatState *
1952 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1954 ModestMsgEditFormatState *format_state = NULL;
1955 ModestMsgEditWindowPrivate *priv;
1956 WPTextBufferFormat *buffer_format;
1958 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1960 buffer_format = g_new0 (WPTextBufferFormat, 1);
1961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1963 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1965 format_state = g_new0 (ModestMsgEditFormatState, 1);
1966 format_state->bold = buffer_format->bold&0x1;
1967 format_state->italics = buffer_format->italic&0x1;
1968 format_state->bullet = buffer_format->bullet&0x1;
1969 format_state->color = buffer_format->color;
1970 format_state->font_size = buffer_format->font_size;
1971 format_state->font_family = wp_get_font_name (buffer_format->font);
1972 format_state->justification = buffer_format->justification;
1973 g_free (buffer_format);
1975 return format_state;
1980 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1981 const ModestMsgEditFormatState *format_state)
1983 ModestMsgEditWindowPrivate *priv;
1984 WPTextBufferFormat *buffer_format;
1985 WPTextBufferFormat *current_format;
1987 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1988 g_return_if_fail (format_state != NULL);
1990 buffer_format = g_new0 (WPTextBufferFormat, 1);
1991 current_format = g_new0 (WPTextBufferFormat, 1);
1993 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1994 gtk_widget_grab_focus (priv->msg_body);
1995 buffer_format->bold = (format_state->bold != FALSE);
1996 buffer_format->italic = (format_state->italics != FALSE);
1997 buffer_format->color = format_state->color;
1998 buffer_format->font_size = format_state->font_size;
1999 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2000 buffer_format->justification = format_state->justification;
2001 buffer_format->bullet = format_state->bullet;
2003 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2005 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2006 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2007 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2008 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2009 buffer_format->cs.font = (buffer_format->font != current_format->font);
2010 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2011 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2013 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2014 if (buffer_format->cs.bold) {
2015 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2016 GINT_TO_POINTER (buffer_format->bold&0x1));
2018 if (buffer_format->cs.italic) {
2019 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2020 GINT_TO_POINTER (buffer_format->italic&0x1));
2022 if (buffer_format->cs.color) {
2023 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2024 GINT_TO_POINTER (&(buffer_format->color)));
2026 if (buffer_format->cs.font_size) {
2027 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2028 GINT_TO_POINTER (buffer_format->font_size));
2030 if (buffer_format->cs.justification) {
2031 switch (buffer_format->justification) {
2032 case GTK_JUSTIFY_LEFT:
2033 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2034 GINT_TO_POINTER(TRUE));
2036 case GTK_JUSTIFY_CENTER:
2037 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2038 GINT_TO_POINTER(TRUE));
2040 case GTK_JUSTIFY_RIGHT:
2041 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2042 GINT_TO_POINTER(TRUE));
2049 if (buffer_format->cs.font) {
2050 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2051 GINT_TO_POINTER (buffer_format->font));
2053 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2054 if (buffer_format->cs.bullet) {
2055 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2056 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2058 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2060 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2062 g_free (buffer_format);
2063 g_free (current_format);
2065 /* Check dimming rules */
2066 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2067 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2071 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2073 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2075 ModestWindowPrivate *parent_priv;
2076 ModestMsgEditWindowPrivate *priv;
2078 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2079 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2081 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2082 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2083 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2084 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2086 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2087 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2088 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2091 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2093 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2094 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2096 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2097 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2099 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2100 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2103 switch (buffer_format->justification)
2105 case GTK_JUSTIFY_LEFT:
2106 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2108 case GTK_JUSTIFY_CENTER:
2109 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2111 case GTK_JUSTIFY_RIGHT:
2112 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2119 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2121 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2122 G_CALLBACK (modest_msg_edit_window_color_button_change),
2124 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2125 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2126 G_CALLBACK (modest_msg_edit_window_color_button_change),
2129 if (priv->current_size_index != buffer_format->font_size) {
2133 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2134 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2138 priv->current_size_index = buffer_format->font_size;
2140 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2141 markup = g_strconcat ("<span font_family='Sans'>",
2142 size_text, "</span>", NULL);
2144 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2148 gtk_tree_path_free (path);
2151 if (priv->current_face_index != buffer_format->font) {
2155 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2156 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2160 priv->current_face_index = buffer_format->font;
2161 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2162 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2163 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2170 g_free (buffer_format);
2174 #ifdef MODEST_HILDON_VERSION_0
2176 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2179 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2180 ModestMsgEditWindowPrivate *priv;
2181 GtkWidget *dialog = NULL;
2183 GdkColor *new_color = NULL;
2185 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2186 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2188 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2189 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2190 g_free (buffer_format);
2192 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2193 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2194 if (new_color != NULL) {
2195 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2196 (gpointer) new_color);
2199 gtk_widget_destroy (dialog);
2204 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2207 ModestMsgEditWindowPrivate *priv;
2208 GtkWidget *dialog = NULL;
2210 GdkColor *old_color = NULL;
2211 const GdkColor *new_color = NULL;
2213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2214 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2216 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2217 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2219 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2220 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2221 if (new_color != NULL)
2222 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2224 gtk_widget_destroy (dialog);
2230 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2233 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2234 ModestMsgEditWindowPrivate *priv;
2235 GtkWidget *dialog = NULL;
2237 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2238 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2240 dialog = hildon_color_chooser_new ();
2241 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2242 g_free (buffer_format);
2244 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2246 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2247 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2250 gtk_widget_destroy (dialog);
2255 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2258 ModestMsgEditWindowPrivate *priv;
2259 GtkWidget *dialog = NULL;
2260 GdkColor *old_color = NULL;
2262 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2263 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2265 dialog = hildon_color_chooser_new ();
2266 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2268 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2270 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2271 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2273 gtk_widget_destroy (dialog);
2276 #endif /*!MODEST_HILDON_VERSION_0*/
2281 create_stream_for_uri (const gchar* uri)
2286 TnyStream *result = NULL;
2288 GnomeVFSHandle *handle = NULL;
2289 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2290 if (test == GNOME_VFS_OK) {
2291 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2292 /* Streams over OBEX (Bluetooth) are not seekable but
2293 * we expect them to be (we might need to read them
2294 * several times). So if this is a Bluetooth URI just
2295 * read the whole file into memory (this is not a fast
2296 * protocol so we can assume that these files are not
2297 * going to be very big) */
2298 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2299 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2300 TnyStream *memstream = tny_camel_mem_stream_new ();
2301 tny_stream_write_to_stream (vfssstream, memstream);
2302 g_object_unref (vfssstream);
2305 result = vfssstream;
2313 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2316 ModestMsgEditWindowPrivate *priv;
2317 GtkWidget *dialog = NULL;
2319 GSList *uris = NULL;
2320 GSList *uri_node = NULL;
2322 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2324 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2325 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2326 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2328 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2330 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2331 GTK_WINDOW (dialog), GTK_WINDOW (window));
2333 response = gtk_dialog_run (GTK_DIALOG (dialog));
2335 case GTK_RESPONSE_OK:
2337 gchar *current_folder;
2338 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2339 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2340 if (current_folder && current_folder != '\0') {
2342 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2343 current_folder, &err);
2345 g_debug ("Error storing latest used folder: %s", err->message);
2349 g_free (current_folder);
2355 gtk_widget_destroy (dialog);
2357 g_object_ref (window);
2358 /* The operation could take some time so allow the dialog to be closed */
2359 while (gtk_events_pending ())
2360 gtk_main_iteration ();
2362 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2364 GnomeVFSHandle *handle = NULL;
2365 GnomeVFSResult result;
2366 GtkTextIter position;
2367 GtkTextMark *insert_mark;
2369 uri = (const gchar *) uri_node->data;
2370 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2371 if (result == GNOME_VFS_OK) {
2373 GnomeVFSFileInfo *info;
2374 gchar *filename, *basename, *escaped_filename;
2375 TnyMimePart *mime_part;
2377 const gchar *mime_type = NULL;
2378 GnomeVFSURI *vfs_uri;
2379 guint64 stream_size;
2381 gnome_vfs_close (handle);
2382 vfs_uri = gnome_vfs_uri_new (uri);
2384 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2385 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2386 g_free (escaped_filename);
2387 gnome_vfs_uri_unref (vfs_uri);
2388 info = gnome_vfs_file_info_new ();
2390 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2391 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2393 mime_type = gnome_vfs_file_info_get_mime_type (info);
2395 mime_part = tny_platform_factory_new_mime_part
2396 (modest_runtime_get_platform_factory ());
2398 TnyStream *stream = create_stream_for_uri (uri);
2400 if (stream == NULL) {
2402 modest_platform_information_banner (NULL, NULL,
2403 _FM("sfil_ib_opening_not_allowed"));
2405 g_object_unref (mime_part);
2406 gnome_vfs_file_info_unref (info);
2410 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2412 content_id = g_strdup_printf ("%d", priv->next_cid);
2413 tny_mime_part_set_content_id (mime_part, content_id);
2414 g_free (content_id);
2417 basename = g_path_get_basename (filename);
2418 tny_mime_part_set_filename (mime_part, basename);
2421 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2423 if (pixbuf != NULL) {
2424 priv->images_size += stream_size;
2425 priv->images_count ++;
2426 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2427 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2428 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2429 tny_mime_part_get_content_id (mime_part), pixbuf);
2430 g_object_unref (pixbuf);
2432 tny_list_prepend (priv->images, (GObject *) mime_part);
2433 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2435 modest_platform_information_banner (NULL, NULL,
2436 _("mail_ib_file_operation_failed"));
2440 g_object_unref (mime_part);
2441 gnome_vfs_file_info_unref (info);
2445 g_object_unref (window);
2449 on_attach_file_response (GtkDialog *dialog,
2453 GSList *uris = NULL;
2455 GnomeVFSFileSize total_size, allowed_size;
2456 ModestMsgEditWindow *window;
2457 ModestMsgEditWindowPrivate *priv;
2462 case GTK_RESPONSE_OK:
2464 gchar *current_folder;
2466 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2467 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2468 if (current_folder && current_folder != '\0') {
2470 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2471 current_folder, &err);
2473 g_debug ("Error storing latest used folder: %s", err->message);
2477 g_free (current_folder);
2484 window = MODEST_MSG_EDIT_WINDOW (user_data);
2485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2487 /* allowed size is the maximum size - what's already there */
2488 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2489 &att_num, &att_size);
2490 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2493 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2495 const gchar *uri = (const gchar *) uri_node->data;
2498 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2500 if (total_size > allowed_size) {
2501 g_debug ("%s: total size: %u",
2502 __FUNCTION__, (unsigned int)total_size);
2505 allowed_size -= total_size;
2507 g_slist_foreach (uris, (GFunc) g_free, NULL);
2508 g_slist_free (uris);
2510 gtk_widget_destroy (GTK_WIDGET (dialog));
2514 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2516 GtkWidget *dialog = NULL;
2517 ModestMsgEditWindowPrivate *priv;
2520 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2522 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2524 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2527 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2528 GTK_FILE_CHOOSER_ACTION_OPEN);
2529 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2530 conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2531 if (conf_folder && conf_folder[0] != '\0') {
2532 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2535 /* Set the default folder to images folder */
2536 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2537 ".documents", NULL);
2538 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2539 g_free (docs_folder);
2541 g_free (conf_folder);
2542 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2543 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2544 GTK_WINDOW (dialog), GTK_WINDOW (window));
2546 /* Connect to response & show */
2547 g_signal_connect (dialog, "response",
2548 G_CALLBACK (on_attach_file_response), window);
2549 gtk_widget_show (dialog);
2554 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2556 GnomeVFSFileSize allowed_size)
2559 GnomeVFSHandle *handle = NULL;
2560 ModestMsgEditWindowPrivate *priv;
2561 GnomeVFSResult result;
2562 GnomeVFSFileSize size = 0;
2563 g_return_val_if_fail (window, 0);
2564 g_return_val_if_fail (uri, 0);
2566 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2568 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2569 if (result == GNOME_VFS_OK) {
2570 TnyMimePart *mime_part;
2572 const gchar *mime_type = NULL;
2574 gchar *escaped_filename;
2577 GnomeVFSFileInfo *info;
2578 GnomeVFSURI *vfs_uri;
2580 gnome_vfs_close (handle);
2581 vfs_uri = gnome_vfs_uri_new (uri);
2584 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2585 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2586 g_free (escaped_filename);
2587 gnome_vfs_uri_unref (vfs_uri);
2589 info = gnome_vfs_file_info_new ();
2591 if (gnome_vfs_get_file_info (uri,
2593 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2595 mime_type = gnome_vfs_file_info_get_mime_type (info);
2596 mime_part = tny_platform_factory_new_mime_part
2597 (modest_runtime_get_platform_factory ());
2599 /* try to get the attachment's size; this may fail for weird
2600 * file systems, like obex, upnp... */
2601 if (allowed_size != 0 &&
2602 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2604 if (size > allowed_size) {
2605 modest_platform_information_banner (NULL, NULL,
2606 _("mail_ib_error_attachment_size"));
2611 g_debug ("%s: could not get attachment size", __FUNCTION__);
2613 stream = create_stream_for_uri (uri);
2615 if (stream == NULL) {
2617 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2619 g_object_unref (mime_part);
2621 gnome_vfs_file_info_unref (info);
2625 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2626 g_object_unref (stream);
2628 content_id = g_strdup_printf ("%d", priv->next_cid);
2629 tny_mime_part_set_content_id (mime_part, content_id);
2630 g_free (content_id);
2633 basename = g_path_get_basename (filename);
2634 tny_mime_part_set_filename (mime_part, basename);
2637 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2638 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2640 info->size == 0, info->size);
2641 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2642 gtk_widget_show_all (priv->attachments_caption);
2643 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2645 g_object_unref (mime_part);
2646 gnome_vfs_file_info_unref (info);
2653 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2656 ModestMsgEditWindowPrivate *priv;
2659 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2660 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2662 if (att_list == NULL) {
2663 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2664 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2665 g_object_unref (att_list);
2669 g_object_ref (att_list);
2672 if (tny_list_get_length (att_list) == 0) {
2673 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2675 gboolean dialog_response;
2676 gchar *message = NULL;
2677 gchar *filename = NULL;
2679 if (tny_list_get_length (att_list) == 1) {
2681 iter = tny_list_create_iterator (att_list);
2682 part = (TnyMimePart *) tny_iterator_get_current (iter);
2683 g_object_unref (iter);
2684 if (TNY_IS_MSG (part)) {
2685 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2687 filename = tny_header_dup_subject (header);
2688 g_object_unref (header);
2690 if (filename == NULL) {
2691 filename = g_strdup (_("mail_va_no_subject"));
2694 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2696 g_object_unref (part);
2698 filename = g_strdup ("");
2700 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2701 "emev_nc_delete_attachments",
2702 tny_list_get_length (att_list)), filename);
2705 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2709 if (dialog_response != GTK_RESPONSE_OK) {
2710 g_object_unref (att_list);
2714 for (iter = tny_list_create_iterator (att_list);
2715 !tny_iterator_is_done (iter);
2716 tny_iterator_next (iter)) {
2717 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2718 const gchar *att_id;
2719 tny_list_remove (priv->attachments, (GObject *) mime_part);
2721 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2723 if (tny_list_get_length (priv->attachments) == 0)
2724 gtk_widget_hide (priv->attachments_caption);
2725 att_id = tny_mime_part_get_content_id (mime_part);
2727 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2729 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2730 g_object_unref (mime_part);
2732 g_object_unref (iter);
2735 g_object_unref (att_list);
2737 /* if the last attachment has been removed, focus the Subject: field */
2738 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2739 gtk_widget_grab_focus (priv->subject_field);
2743 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2746 ModestMsgEditWindowPrivate *priv;
2747 GdkColor *new_color;
2748 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2750 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2751 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2754 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2756 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2758 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2760 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2765 font_size_clicked (GtkToolButton *button,
2766 ModestMsgEditWindow *window)
2768 ModestMsgEditWindowPrivate *priv;
2769 GtkWidget *selector, *dialog;
2771 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2773 selector = hildon_touch_selector_new ();
2774 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2775 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2777 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2778 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2779 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2781 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2785 WPTextBufferFormat format;
2787 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2789 memset (&format, 0, sizeof (format));
2790 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2792 format.cs.font_size = TRUE;
2793 format.cs.text_position = TRUE;
2794 format.cs.font = TRUE;
2795 format.font_size = new_index;
2796 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2798 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2799 GINT_TO_POINTER (new_index)))
2800 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2802 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2803 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2804 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2805 size_text, "</span>", NULL);
2807 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2811 gtk_widget_destroy (dialog);
2813 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2818 font_face_clicked (GtkToolButton *button,
2819 ModestMsgEditWindow *window)
2821 ModestMsgEditWindowPrivate *priv;
2822 GtkWidget *selector, *dialog;
2823 GtkCellRenderer *renderer;
2825 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2827 selector = hildon_touch_selector_new ();
2828 renderer = gtk_cell_renderer_text_new ();
2829 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2830 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2831 renderer, "family", 0, "text", 0, NULL);
2832 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2834 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2835 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2836 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2838 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2839 gint new_font_index;
2843 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2844 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2845 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2849 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2851 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2852 GINT_TO_POINTER(new_font_index)))
2853 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2855 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2856 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2858 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2862 gtk_tree_path_free (path);
2865 gtk_widget_destroy (dialog);
2867 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2872 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2875 ModestMsgEditWindowPrivate *priv = NULL;
2876 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2878 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2879 if (!priv->update_caption_visibility)
2882 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2884 gtk_widget_show (priv->cc_caption);
2886 gtk_widget_hide (priv->cc_caption);
2888 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2892 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2895 ModestMsgEditWindowPrivate *priv = NULL;
2896 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2898 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2899 if (!priv->update_caption_visibility)
2902 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2904 gtk_widget_show (priv->bcc_caption);
2906 gtk_widget_hide (priv->bcc_caption);
2908 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2912 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2913 ModestRecptEditor *editor)
2915 ModestMsgEditWindowPrivate *priv;
2917 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2918 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2920 /* we check for low-mem; in that case, show a warning, and don't allow
2921 * for the addressbook
2923 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2928 if (editor == NULL) {
2929 GtkWidget *view_focus, *parent;
2930 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2932 /* This code should be kept in sync with ModestRecptEditor. The
2933 textview inside the recpt editor is the one that really gets the
2934 focus. As it's inside a scrolled window, and this one inside the
2935 hbox recpt editor inherits from, we'll need to go up in the
2936 hierarchy to know if the text view is part of the recpt editor
2937 or if it's a different text entry */
2938 parent = gtk_widget_get_parent (view_focus);
2939 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2940 editor = MODEST_RECPT_EDITOR (parent);
2943 editor = MODEST_RECPT_EDITOR (priv->to_field);
2946 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2950 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2954 modest_msg_edit_window_open_addressbook (window, NULL);
2958 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2959 gboolean show_toolbar)
2961 ModestWindowPrivate *parent_priv;
2962 ModestMsgEditWindowPrivate *priv;
2964 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2965 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2966 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2968 /* We can not just use the code of
2969 modest_msg_edit_window_setup_toolbar because it has a
2970 mixture of both initialization and creation code. */
2972 gint current_format;
2973 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2974 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2975 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2976 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2978 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2981 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2986 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2987 TnyHeaderFlags priority_flags)
2989 ModestMsgEditWindowPrivate *priv;
2990 ModestWindowPrivate *parent_priv;
2992 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2994 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2995 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2997 if (priv->priority_flags != priority_flags) {
2998 GtkAction *priority_action = NULL;
3000 priv->priority_flags = priority_flags;
3002 switch (priority_flags) {
3003 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3004 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3005 MODEST_HEADER_ICON_HIGH,
3006 HILDON_ICON_SIZE_SMALL);
3007 gtk_widget_show (priv->priority_icon);
3008 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3009 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3011 case TNY_HEADER_FLAG_LOW_PRIORITY:
3012 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3013 MODEST_HEADER_ICON_LOW,
3014 HILDON_ICON_SIZE_SMALL);
3015 gtk_widget_show (priv->priority_icon);
3016 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3017 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3020 gtk_widget_hide (priv->priority_icon);
3021 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3022 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3025 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3026 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3028 gtk_widget_queue_resize (priv->subject_box);
3032 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3035 ModestMsgEditWindowPrivate *priv;
3036 ModestWindowPrivate *parent_priv;
3037 gint current_format;
3039 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3041 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3044 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3045 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3047 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3049 if (parent_priv->toolbar) {
3050 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3051 gtk_widget_hide (parent_priv->toolbar);
3053 gtk_widget_show (parent_priv->toolbar);
3057 if (current_format != file_format) {
3058 switch (file_format) {
3059 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3060 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3061 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3063 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3067 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3068 response = gtk_dialog_run (GTK_DIALOG (dialog));
3069 gtk_widget_destroy (dialog);
3070 if (response == GTK_RESPONSE_OK) {
3071 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3072 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3074 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3075 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3080 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3081 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3082 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3087 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3090 ModestMsgEditWindowPrivate *priv;
3091 WPTextBufferFormat oldfmt, fmt;
3092 gint old_position = 0;
3096 GdkColor *color = NULL;
3097 gboolean bold, bold_set, italic, italic_set;
3098 gboolean underline, underline_set;
3099 gboolean strikethrough, strikethrough_set;
3100 gboolean position_set;
3101 gboolean font_size_set, font_set, color_set;
3104 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3105 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3107 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3108 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3109 GTK_WINDOW(dialog), GTK_WINDOW (window));
3111 /* First we get the currently selected font information */
3112 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3114 switch (oldfmt.text_position) {
3115 case TEXT_POSITION_NORMAL:
3118 case TEXT_POSITION_SUPERSCRIPT:
3126 g_object_set (G_OBJECT (dialog),
3127 "bold", oldfmt.bold != FALSE,
3128 "bold-set", !oldfmt.cs.bold,
3129 "underline", oldfmt.underline != FALSE,
3130 "underline-set", !oldfmt.cs.underline,
3131 "italic", oldfmt.italic != FALSE,
3132 "italic-set", !oldfmt.cs.italic,
3133 "strikethrough", oldfmt.strikethrough != FALSE,
3134 "strikethrough-set", !oldfmt.cs.strikethrough,
3135 "color", &oldfmt.color,
3136 "color-set", !oldfmt.cs.color,
3137 "size", wp_font_size[oldfmt.font_size],
3138 "size-set", !oldfmt.cs.font_size,
3139 "position", old_position,
3140 "position-set", !oldfmt.cs.text_position,
3141 "family", wp_get_font_name (oldfmt.font),
3142 "family-set", !oldfmt.cs.font,
3145 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3146 GTK_WINDOW (dialog), GTK_WINDOW (window));
3147 gtk_widget_show_all (dialog);
3148 priv->font_dialog = dialog;
3149 response = gtk_dialog_run (GTK_DIALOG (dialog));
3150 priv->font_dialog = NULL;
3151 if (response == GTK_RESPONSE_OK) {
3153 g_object_get( dialog,
3155 "bold-set", &bold_set,
3156 "underline", &underline,
3157 "underline-set", &underline_set,
3159 "italic-set", &italic_set,
3160 "strikethrough", &strikethrough,
3161 "strikethrough-set", &strikethrough_set,
3163 "color-set", &color_set,
3165 "size-set", &font_size_set,
3166 "family", &font_name,
3167 "family-set", &font_set,
3168 "position", &position,
3169 "position-set", &position_set,
3174 if (response == GTK_RESPONSE_OK) {
3175 memset(&fmt, 0, sizeof(fmt));
3181 fmt.italic = italic;
3182 fmt.cs.italic = TRUE;
3184 if (underline_set) {
3185 fmt.underline = underline;
3186 fmt.cs.underline = TRUE;
3188 if (strikethrough_set) {
3189 fmt.strikethrough = strikethrough;
3190 fmt.cs.strikethrough = TRUE;
3195 ? TEXT_POSITION_NORMAL
3196 : ( ( position == 1 )
3197 ? TEXT_POSITION_SUPERSCRIPT
3198 : TEXT_POSITION_SUBSCRIPT );
3199 fmt.cs.text_position = TRUE;
3200 fmt.font_size = oldfmt.font_size;
3204 fmt.cs.color = TRUE;
3207 fmt.font = wp_get_font_index(font_name,
3212 if (font_size_set) {
3213 fmt.cs.font_size = TRUE;
3214 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3216 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3217 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3219 gtk_widget_destroy (dialog);
3221 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3225 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3227 ModestMsgEditWindowPrivate *priv;
3229 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3230 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3232 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3234 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3235 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3239 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3241 ModestMsgEditWindowPrivate *priv;
3243 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3244 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3246 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3248 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3249 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3254 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3256 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 priv->can_undo = can_undo;
3262 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3264 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3266 priv->can_redo = can_redo;
3270 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3272 ModestMsgEditWindowPrivate *priv;
3273 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3274 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3276 return priv->can_undo;
3280 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3282 ModestMsgEditWindowPrivate *priv;
3283 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3286 return priv->can_redo;
3291 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3294 GtkTextIter match_start, match_end;
3296 if (image_id == NULL)
3299 gtk_text_buffer_get_start_iter (buffer, &iter);
3301 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3302 GSList *tags = gtk_text_iter_get_tags (&match_start);
3304 for (node = tags; node != NULL; node = g_slist_next (node)) {
3305 GtkTextTag *tag = (GtkTextTag *) node->data;
3306 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3307 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3308 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3310 offset = gtk_text_iter_get_offset (&match_start);
3311 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3312 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3316 gtk_text_iter_forward_char (&iter);
3321 message_is_empty (ModestMsgEditWindow *window)
3323 ModestMsgEditWindowPrivate *priv = NULL;
3325 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3326 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3328 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3329 * so we can ignore markup.
3331 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3334 count = gtk_text_buffer_get_char_count (buf);
3340 msg_body_focus (GtkWidget *focus,
3341 GdkEventFocus *event,
3345 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3346 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3347 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3352 recpt_field_changed (GtkTextBuffer *buffer,
3353 ModestMsgEditWindow *editor)
3355 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3356 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3360 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3362 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3363 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3367 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3370 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3371 GtkTextBuffer *buffer;
3373 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3374 gtk_text_buffer_set_modified (buffer, modified);
3375 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3376 gtk_text_buffer_set_modified (buffer, modified);
3377 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3378 gtk_text_buffer_set_modified (buffer, modified);
3379 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3383 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3385 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3386 const char *account_name;
3387 GtkTextBuffer *buffer;
3389 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3390 if (gtk_text_buffer_get_modified (buffer))
3392 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3393 if (gtk_text_buffer_get_modified (buffer))
3395 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3396 if (gtk_text_buffer_get_modified (buffer))
3398 if (gtk_text_buffer_get_modified (priv->text_buffer))
3401 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3402 if (priv->original_mailbox) {
3403 if (!account_name || strcmp (account_name, priv->original_mailbox))
3405 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3416 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3418 ModestMsgEditWindowPrivate *priv = NULL;
3420 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3421 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3423 /* check if there's no recipient added */
3424 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3425 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3426 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3427 /* no recipient contents, then select contacts */
3428 modest_msg_edit_window_open_addressbook (window, NULL);
3432 g_object_ref (window);
3433 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3434 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3435 g_object_unref (window);
3438 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3439 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3440 g_object_unref (window);
3443 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3444 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3445 g_object_unref (window);
3449 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3450 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3451 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3452 g_object_unref (window);
3459 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3460 ModestMsgEditWindow *window)
3462 modest_msg_edit_window_offer_attach_file (window);
3466 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3468 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3470 return priv->clipboard_text;
3474 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3476 ModestMsgEditWindow *window)
3478 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3479 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3482 /* It could happen that the window was already closed */
3483 if (!GTK_WIDGET_VISIBLE (window))
3486 g_object_ref (window);
3487 text = gtk_clipboard_wait_for_text (selection_clipboard);
3489 if (priv->clipboard_text != NULL) {
3490 g_free (priv->clipboard_text);
3492 priv->clipboard_text = text;
3494 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3496 g_object_unref (window);
3499 static gboolean clipboard_owner_change_idle (gpointer userdata)
3501 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3502 ModestMsgEditWindowPrivate *priv;
3504 gdk_threads_enter ();
3505 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3508 priv->clipboard_owner_idle = 0;
3509 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3510 gdk_threads_leave ();
3516 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3518 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3519 if (priv->clipboard_owner_idle == 0) {
3520 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3521 clipboard_owner_change_idle,
3522 g_object_ref (window),
3528 subject_field_move_cursor (GtkEntry *entry,
3529 GtkMovementStep step,
3534 /* It could happen that the window was already closed */
3535 if (!GTK_WIDGET_VISIBLE (window))
3538 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3542 update_window_title (ModestMsgEditWindow *window)
3544 ModestMsgEditWindowPrivate *priv = NULL;
3545 const gchar *subject;
3547 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3548 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3549 if (subject == NULL || subject[0] == '\0')
3550 subject = _("mail_va_new_email");
3552 gtk_window_set_title (GTK_WINDOW (window), subject);
3558 body_insert_text (GtkTextBuffer *buffer,
3559 GtkTextIter *location,
3562 ModestMsgEditWindow *window)
3564 GtkTextIter end_iter;
3568 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3570 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3572 offset = gtk_text_iter_get_offset (&end_iter);
3573 utf8_len = g_utf8_strlen (text, len);
3575 if (offset + utf8_len > MAX_BODY_LENGTH) {
3576 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3577 if (offset < MAX_BODY_LENGTH)
3582 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3584 /* Prevent endless recursion */
3585 result = g_strndup (text, utf8_end - text);
3586 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3587 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3588 (gpointer) result, (gpointer) (utf8_end - text),
3590 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3594 if (offset + utf8_len > MAX_BODY_LENGTH) {
3595 if (priv->max_chars_banner == NULL) {
3596 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3597 _CS("ckdg_ib_maximum_characters_reached"));
3598 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3604 subject_field_changed (GtkEditable *editable,
3605 ModestMsgEditWindow *window)
3607 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3608 update_window_title (window);
3609 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3610 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3611 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3614 subject_field_insert_text (GtkEditable *editable,
3616 gint new_text_length,
3618 ModestMsgEditWindow *window)
3620 GString *result = g_string_new ("");
3622 gint result_len = 0;
3623 const gchar *entry_text = NULL;
3626 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3627 old_length = g_utf8_strlen (entry_text, -1);
3629 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3630 gunichar c = g_utf8_get_char_validated (current, 8);
3631 /* Invalid unichar, stop */
3637 result = g_string_append_unichar (result, c);
3641 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3642 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3645 /* Prevent endless recursion */
3646 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3647 g_signal_emit_by_name (editable, "insert-text",
3648 (gpointer) result->str, (gpointer) result->len,
3649 (gpointer) position, (gpointer) window);
3650 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3654 if (result_len + old_length > 1000) {
3655 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3656 _CS("ckdg_ib_maximum_characters_reached"));
3658 g_string_free (result, TRUE);
3662 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3665 ModestMsgEditWindowPrivate *priv = NULL;
3667 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3668 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3670 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3673 gtk_widget_show_all (priv->find_toolbar);
3674 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3676 gtk_widget_hide_all (priv->find_toolbar);
3677 gtk_widget_grab_focus (priv->msg_body);
3682 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3684 GtkTextIter *match_start,
3685 GtkTextIter *match_end)
3687 GtkTextIter end_iter;
3688 gchar *str_casefold;
3691 gchar *range_casefold;
3694 gboolean result = FALSE;
3701 gtk_text_iter_forward_to_end (&end_iter);
3703 str_casefold = g_utf8_casefold (str, -1);
3704 str_chars_n = strlen (str);
3706 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3707 range_casefold = g_utf8_casefold (range_text, -1);
3708 range_chars_n = strlen (range_casefold);
3710 if (range_chars_n < str_chars_n) {
3711 g_free (str_casefold);
3712 g_free (range_text);
3713 g_free (range_casefold);
3717 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3718 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3719 if (!g_utf8_collate (range_subtext, str_casefold)) {
3720 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3722 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3723 match_start, match_end, NULL)) {
3724 g_debug ("Matched string with collate, but not matched in model");
3726 g_free (found_text);
3728 g_free (range_subtext);
3732 g_free (str_casefold);
3733 g_free (range_text);
3734 g_free (range_casefold);
3741 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3742 ModestMsgEditWindow *window)
3744 gchar *current_search = NULL;
3745 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3747 GtkTextIter selection_start, selection_end;
3748 GtkTextIter match_start, match_end;
3749 gboolean continue_search = FALSE;
3751 if (message_is_empty (window)) {
3752 g_free (priv->last_search);
3753 priv->last_search = NULL;
3754 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3758 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3759 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3760 g_free (current_search);
3761 g_free (priv->last_search);
3762 priv->last_search = NULL;
3763 /* Information banner about empty search */
3764 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3768 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3769 continue_search = TRUE;
3771 g_free (priv->last_search);
3772 priv->last_search = g_strdup (current_search);
3775 if (continue_search) {
3776 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3777 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3778 &match_start, &match_end);
3780 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3782 GtkTextIter buffer_start;
3783 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3784 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3785 &match_start, &match_end);
3787 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3790 /* Mark as selected the string found in search */
3792 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3793 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3794 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3796 g_free (priv->last_search);
3797 priv->last_search = NULL;
3799 g_free (current_search);
3803 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3805 ModestMsgEditWindowPrivate *priv;
3807 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3812 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3815 ModestMsgEditWindowPrivate *priv;
3817 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3822 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3823 ModestMsgEditWindow *window)
3825 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3829 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3832 ModestMsgEditWindowPrivate *priv;
3833 TnyHeader *header = NULL;
3835 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3836 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3838 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3840 if (priv->draft_msg != NULL) {
3841 g_object_unref (priv->draft_msg);
3844 if (draft != NULL) {
3845 g_object_ref (draft);
3846 header = tny_msg_get_header (draft);
3847 if (priv->msg_uid) {
3848 g_free (priv->msg_uid);
3849 priv->msg_uid = NULL;
3851 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3854 priv->draft_msg = draft;
3858 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3859 GtkTextIter *start, GtkTextIter *end,
3862 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3863 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3866 if (tag == NULL) return;
3867 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3868 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3869 replace_with_images (window, priv->images);
3874 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3877 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3879 g_return_if_fail (TNY_IS_MIME_PART (part));
3880 tny_list_prepend (priv->attachments, (GObject *) part);
3881 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3882 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3883 gtk_widget_show_all (priv->attachments_caption);
3884 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3888 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3890 ModestMsgEditWindowPrivate *priv;
3892 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3893 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3895 return priv->msg_uid;
3899 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3900 ModestMsgEditWindowWidgetType widget_type)
3902 ModestMsgEditWindowPrivate *priv;
3904 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3905 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3907 switch (widget_type) {
3908 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3909 return priv->msg_body;
3911 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3912 return priv->to_field;
3914 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3915 return priv->cc_field;
3917 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3918 return priv->bcc_field;
3920 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3921 return priv->subject_field;
3923 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3924 return priv->attachments_view;
3932 remove_tags (WPTextBuffer *buffer)
3934 GtkTextIter start, end;
3936 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3937 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3939 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3943 on_account_removed (TnyAccountStore *account_store,
3944 TnyAccount *account,
3947 /* Do nothing if it's a store account, because we use the
3948 transport to send the messages */
3949 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3950 const gchar *parent_acc = NULL;
3951 const gchar *our_acc = NULL;
3953 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3954 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3955 /* Close this window if I'm showing a message of the removed account */
3956 if (strcmp (parent_acc, our_acc) == 0)
3957 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3961 static void update_signature (ModestMsgEditWindow *self,
3962 const gchar *old_account,
3963 const gchar *new_account)
3965 ModestMsgEditWindowPrivate *priv;
3966 gboolean has_old_signature, has_new_signature;
3968 GtkTextIter match_start, match_end;
3969 ModestAccountMgr *mgr;
3971 gchar *full_signature;
3973 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3975 gtk_text_buffer_begin_user_action (priv->text_buffer);
3977 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3978 mgr = modest_runtime_get_account_mgr ();
3982 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3983 if (has_old_signature) {
3984 full_signature = g_strconcat ("\n--\n", signature, NULL);
3985 if (gtk_text_iter_forward_search (&iter, full_signature, 0, &match_start, &match_end, NULL)) {
3986 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3988 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3989 &match_start, &match_end, NULL)) {
3992 g_free (full_signature);
3997 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3998 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3999 if (has_new_signature) {
4000 full_signature = g_strconcat ("\n--\n", signature, NULL);
4001 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4002 g_free (full_signature);
4005 gtk_text_buffer_end_user_action (priv->text_buffer);
4008 static void update_branding (ModestMsgEditWindow *self,
4009 const gchar *new_account)
4011 ModestMsgEditWindowPrivate *priv;
4012 ModestAccountMgr *mgr;
4013 const GdkPixbuf *new_icon = NULL;
4014 gchar *new_label = NULL;
4016 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4018 mgr = modest_runtime_get_account_mgr ();
4020 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4022 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4023 gtk_widget_show (priv->brand_icon);
4025 gtk_widget_hide (priv->brand_icon);
4028 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4029 gtk_widget_show (priv->brand_label);
4032 gtk_widget_hide (priv->brand_label);
4037 from_field_changed (HildonPickerButton *button,
4038 ModestMsgEditWindow *self)
4040 ModestMsgEditWindowPrivate *priv;
4041 gchar *old_account, *new_account;
4043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4045 old_account = priv->last_from_account;
4046 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4047 new_account = priv->last_from_account;
4049 update_signature (self, old_account, new_account);
4050 update_branding (self, new_account);
4054 typedef struct _MessageSettingsHelper {
4055 ModestMsgEditWindow *window;
4056 GSList *priority_group;
4057 GSList *format_group;
4058 GtkToggleButton *current_priority;
4059 GtkToggleButton *current_format;
4060 } MessageSettingsHelper;
4063 on_priority_toggle (GtkToggleButton *button,
4064 MessageSettingsHelper *helper)
4067 ModestMsgEditWindowPrivate *priv;
4069 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4070 if (gtk_toggle_button_get_active (button)) {
4072 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4073 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4074 if ((node_button != button) &&
4075 gtk_toggle_button_get_active (node_button)) {
4076 gtk_toggle_button_set_active (node_button, FALSE);
4079 helper->current_priority = button;
4081 gboolean found = FALSE;
4082 /* If no one is active, activate it again */
4083 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4084 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4085 if (gtk_toggle_button_get_active (node_button)) {
4091 gtk_toggle_button_set_active (button, TRUE);
4097 on_format_toggle (GtkToggleButton *button,
4098 MessageSettingsHelper *helper)
4101 ModestMsgEditWindowPrivate *priv;
4103 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4104 if (gtk_toggle_button_get_active (button)) {
4106 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4107 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4108 if ((node_button != button) &&
4109 gtk_toggle_button_get_active (node_button)) {
4110 gtk_toggle_button_set_active (node_button, FALSE);
4113 helper->current_format = button;
4115 gboolean found = FALSE;
4116 /* If no one is active, activate it again */
4117 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4118 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4119 if (gtk_toggle_button_get_active (node_button)) {
4125 gtk_toggle_button_set_active (button, TRUE);
4132 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4137 GtkWidget *priority_hbox;
4138 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4139 GtkWidget *captioned;
4140 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4141 GtkWidget *format_hbox;
4142 GtkWidget *html_toggle, *text_toggle;
4143 ModestMsgEditWindowPrivate *priv;
4144 MessageSettingsHelper helper = {0,};
4146 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4147 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4148 helper.window = window;
4149 helper.priority_group = NULL;
4150 helper.format_group = NULL;
4152 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4153 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4155 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4156 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4157 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4158 vbox = gtk_vbox_new (FALSE, 0);
4159 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4160 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4161 gtk_container_add (GTK_CONTAINER (align), vbox);
4162 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4163 gtk_widget_show (align);
4164 gtk_widget_show (vbox);
4166 /* Priority toggles */
4167 priority_hbox = gtk_hbox_new (TRUE, 0);
4168 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4169 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4170 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4171 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4172 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4173 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4174 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4175 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4176 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4177 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4178 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4179 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4180 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4181 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4182 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4183 gtk_widget_show_all (priority_hbox);
4184 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4185 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4186 gtk_widget_show (captioned);
4187 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4189 /* format toggles */
4190 format_hbox = gtk_hbox_new (TRUE, 0);
4191 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4192 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4193 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4194 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4195 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4196 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4197 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4198 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4199 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4200 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4201 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4202 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4203 gtk_widget_show_all (format_hbox);
4204 gtk_widget_show (format_hbox);
4205 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4208 g_object_unref (title_sizegroup);
4209 g_object_unref (value_sizegroup);
4211 /* Set current values */
4212 switch (priv->priority_flags) {
4213 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4214 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4215 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4217 case TNY_HEADER_FLAG_LOW_PRIORITY:
4218 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4219 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4222 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4223 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4227 switch (modest_msg_edit_window_get_format (window)) {
4228 case MODEST_MSG_EDIT_FORMAT_TEXT:
4229 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4230 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4232 case MODEST_MSG_EDIT_FORMAT_HTML:
4234 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4235 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4239 /* Signal connects */
4240 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4241 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4242 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4243 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4244 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4246 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4247 GTK_WINDOW (dialog), GTK_WINDOW (window));
4249 /* Save settings if the user clicked on done */
4250 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4251 TnyHeaderFlags flags;
4252 ModestMsgEditFormat old_format, new_format;
4254 /* Set priority flags */
4255 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4256 if (priv->priority_flags != flags)
4257 modest_msg_edit_window_set_priority_flags (window, flags);
4259 /* Set edit format */
4260 old_format = modest_msg_edit_window_get_format (window);
4261 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4262 if (old_format != new_format) {
4263 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4264 modest_msg_edit_window_set_file_format (window, file_format);
4268 gtk_widget_destroy (dialog);
4269 g_slist_free (helper.priority_group);
4273 on_message_settings (GtkAction *action,
4274 ModestMsgEditWindow *window)
4276 modest_msg_edit_window_show_msg_settings_dialog (window);
4280 on_cc_button_toggled (HildonCheckButton *button,
4281 ModestMsgEditWindow *window)
4283 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4285 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4286 hildon_check_button_get_active (button));
4290 on_bcc_button_toggled (HildonCheckButton *button,
4291 ModestMsgEditWindow *window)
4293 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4295 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4296 hildon_check_button_get_active (button));
4300 setup_menu (ModestMsgEditWindow *self)
4302 ModestMsgEditWindowPrivate *priv = NULL;
4304 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4306 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4308 /* Settings menu buttons */
4309 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4310 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4312 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4313 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4314 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4316 priv->cc_button = hildon_check_button_new (0);
4317 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4318 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4320 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4322 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4323 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4324 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4325 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4327 priv->bcc_button = hildon_check_button_new (0);
4328 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4329 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4331 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4333 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4334 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4335 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4336 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4338 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4339 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4340 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4341 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4342 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4344 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4345 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4346 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4347 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4348 APP_MENU_CALLBACK (on_message_settings),
4350 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4351 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4356 emit_open_addressbook (GtkButton *button,
4357 ModestRecptEditor *editor)
4359 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4363 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4364 const gchar *label, GtkWidget *control)
4366 GtkWidget *abook_button;
4369 GtkWidget *label_widget;
4371 box = gtk_hbox_new (FALSE, 0);
4373 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4374 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4376 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4377 label_widget = gtk_label_new (label);
4378 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4379 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4381 gtk_container_add (GTK_CONTAINER (align), abook_button);
4382 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4383 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4384 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4385 if (title_size_group)
4386 gtk_size_group_add_widget (title_size_group, label_widget);
4387 if (value_size_group)
4388 gtk_size_group_add_widget (value_size_group, control);
4390 g_signal_connect (G_OBJECT (abook_button), "clicked",
4391 G_CALLBACK (emit_open_addressbook), control);
4397 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4399 ModestMsgEditWindowPrivate *priv = NULL;
4401 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4403 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4404 priv->max_chars_banner = NULL;