1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #include <libgnomevfs/gnome-vfs-mime.h>
75 #include <modest-utils.h>
76 #include "modest-maemo-utils.h"
77 #include <modest-ui-constants.h>
80 #define DEFAULT_FONT_SIZE 3
81 #define DEFAULT_FONT 2
82 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
83 #define DEFAULT_MAIN_VBOX_SPACING 0
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 560
86 #define DEFAULT_FONT_SCALE 1.5
87 #define ATTACHMENT_BUTTON_WIDTH 118
88 #define MAX_FROM_VALUE 36
89 #define MAX_BODY_LENGTH 128*1024
90 #define MAX_BODY_LINES 2048
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void body_insert_text (GtkTextBuffer *buffer,
110 GtkTextIter *location,
113 ModestMsgEditWindow *window);
114 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
115 static void subject_field_insert_text (GtkEditable *editable,
117 gint new_text_length,
119 ModestMsgEditWindow *window);
120 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
122 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
124 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
125 ModestRecptEditor *editor);
126 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
127 ModestMsgEditWindow *window);
129 /* ModestWindow methods implementation */
130 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
131 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
132 gboolean show_toolbar);
133 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
135 ModestMsgEditWindow *window);
136 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
137 static void subject_field_move_cursor (GtkEntry *entry,
138 GtkMovementStep step,
142 static void update_window_title (ModestMsgEditWindow *window);
145 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
146 ModestMsgEditWindow *window);
147 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
148 ModestMsgEditWindow *window);
149 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
151 GtkTextIter *match_start,
152 GtkTextIter *match_end);
154 static void remove_tags (WPTextBuffer *buffer);
156 static void on_account_removed (TnyAccountStore *account_store,
160 static void init_window (ModestMsgEditWindow *obj);
162 gboolean scroll_drag_timeout (gpointer userdata);
163 static void correct_scroll (ModestMsgEditWindow *w);
164 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
165 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
166 ModestMsgEditWindow *userdata);
167 static void text_buffer_mark_set (GtkTextBuffer *buffer,
170 ModestMsgEditWindow *userdata);
171 static void on_message_settings (GtkAction *action,
172 ModestMsgEditWindow *window);
173 static void setup_menu (ModestMsgEditWindow *self);
175 static void from_field_changed (HildonPickerButton *button,
176 ModestMsgEditWindow *self);
177 static void font_size_clicked (GtkToolButton *button,
178 ModestMsgEditWindow *window);
179 static void font_face_clicked (GtkToolButton *button,
180 ModestMsgEditWindow *window);
181 static void update_signature (ModestMsgEditWindow *self,
182 const gchar *old_account,
183 const gchar *new_account);
184 static void update_branding (ModestMsgEditWindow *self,
185 const gchar *new_account);
186 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
187 const gchar *label, GtkWidget *control);
188 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
189 static void DEBUG_BUFFER (WPTextBuffer *buffer)
193 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
195 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
196 while (!gtk_text_iter_is_end (&iter)) {
197 GString *output = g_string_new ("");
198 GSList *toggled_tags;
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
202 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
203 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
204 GtkTextTag *tag = (GtkTextTag *) node->data;
206 g_object_get (G_OBJECT (tag), "name", &name, NULL);
207 output = g_string_append (output, name);
208 g_string_append (output, " ");
210 output = g_string_append (output, "] OPENED [ ");
211 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
212 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
213 GtkTextTag *tag = (GtkTextTag *) node->data;
215 g_object_get (G_OBJECT (tag), "name", &name, NULL);
216 output = g_string_append (output, name);
217 g_string_append (output, " ");
219 output = g_string_append (output, "]\n");
220 g_debug ("%s", output->str);
221 g_string_free (output, TRUE);
222 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
224 g_debug ("END BUFFER");
228 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
229 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
233 /* static gboolean */
234 /* on_key_pressed (GtkWidget *self, */
235 /* GdkEventKey *event, */
236 /* gpointer user_data); */
238 /* list my signals */
245 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
246 struct _ModestMsgEditWindowPrivate {
248 GtkWidget *header_box;
250 ModestPairList *from_field_protos;
251 GtkWidget *from_field;
252 gchar *last_from_account;
253 gchar *original_account_name;
258 gchar *original_mailbox;
262 GtkWidget *bcc_field;
263 GtkWidget *subject_field;
264 GtkWidget *attachments_view;
265 GtkWidget *priority_icon;
266 GtkWidget *subject_box;
267 GtkWidget *send_button;
269 GtkWidget *cc_caption;
270 GtkWidget *bcc_caption;
271 gboolean update_caption_visibility;
272 GtkWidget *attachments_caption;
274 GtkTextBuffer *text_buffer;
276 GtkWidget *font_size_toolitem;
277 GtkWidget *font_face_toolitem;
278 GtkWidget *font_color_button;
279 GtkWidget *font_color_toolitem;
280 GSList *font_items_group;
281 GtkTreeModel *faces_model;
282 gint current_face_index;
283 GtkWidget *font_tool_button_label;
284 GtkTreeModel *sizes_model;
285 gint current_size_index;
286 GtkWidget *size_tool_button_label;
288 GtkWidget *find_toolbar;
291 GtkWidget *font_dialog;
294 guint correct_scroll_idle;
295 guint scroll_drag_timeout_id;
299 TnyList *attachments;
304 TnyHeaderFlags priority_flags;
306 gboolean can_undo, can_redo;
307 gulong clipboard_change_handler_id;
308 gulong default_clipboard_change_handler_id;
309 gulong account_removed_handler_id;
310 guint clipboard_owner_idle;
311 gchar *clipboard_text;
320 GtkWidget *cc_button;
321 GtkWidget *bcc_button;
323 GtkWidget *max_chars_banner;
325 GtkWidget *brand_icon;
326 GtkWidget *brand_label;
327 GtkWidget *brand_container;
330 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
331 MODEST_TYPE_MSG_EDIT_WINDOW, \
332 ModestMsgEditWindowPrivate))
334 static GtkWindowClass *parent_class = NULL;
336 /* uncomment the following if you have defined any signals */
337 /* static guint signals[LAST_SIGNAL] = {0}; */
340 modest_msg_edit_window_get_type (void)
342 static GType my_type = 0;
344 static const GTypeInfo my_info = {
345 sizeof(ModestMsgEditWindowClass),
346 NULL, /* base init */
347 NULL, /* base finalize */
348 (GClassInitFunc) modest_msg_edit_window_class_init,
349 NULL, /* class finalize */
350 NULL, /* class data */
351 sizeof(ModestMsgEditWindow),
353 (GInstanceInitFunc) modest_msg_edit_window_init,
356 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
357 "ModestMsgEditWindow",
365 save_state (ModestWindow *self)
367 modest_widget_memory_save (modest_runtime_get_conf(),
368 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
373 restore_settings (ModestMsgEditWindow *self)
375 ModestConf *conf = NULL;
377 conf = modest_runtime_get_conf ();
379 /* Dim at start clipboard actions */
380 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
385 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
387 GObjectClass *gobject_class;
388 ModestWindowClass *modest_window_class;
389 gobject_class = (GObjectClass*) klass;
390 modest_window_class = (ModestWindowClass*) klass;
392 parent_class = g_type_class_peek_parent (klass);
393 gobject_class->finalize = modest_msg_edit_window_finalize;
395 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
396 modest_window_class->save_state_func = save_state;
397 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
399 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
403 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
405 ModestMsgEditWindowPrivate *priv;
406 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
408 priv->msg_body = NULL;
409 priv->from_field = NULL;
410 priv->to_field = NULL;
411 priv->cc_field = NULL;
412 priv->bcc_field = NULL;
413 priv->subject_field = NULL;
414 priv->attachments = TNY_LIST (tny_simple_list_new ());
415 priv->images = TNY_LIST (tny_simple_list_new ());
416 priv->images_size = 0;
417 priv->images_count = 0;
420 priv->cc_caption = NULL;
421 priv->bcc_caption = NULL;
422 priv->update_caption_visibility = FALSE;
424 priv->priority_flags = 0;
426 priv->find_toolbar = NULL;
427 priv->last_search = NULL;
429 priv->draft_msg = NULL;
430 priv->outbox_msg = NULL;
431 priv->msg_uid = NULL;
433 priv->can_undo = FALSE;
434 priv->can_redo = FALSE;
435 priv->clipboard_change_handler_id = 0;
436 priv->default_clipboard_change_handler_id = 0;
437 priv->account_removed_handler_id = 0;
438 priv->clipboard_owner_idle = 0;
439 priv->clipboard_text = NULL;
442 priv->scroll_drag_timeout_id = 0;
443 priv->correct_scroll_idle = 0;
444 priv->last_upper = 0.0;
446 priv->font_dialog = NULL;
447 priv->app_menu = NULL;
449 priv->references = NULL;
450 priv->in_reply_to = NULL;
451 priv->max_chars_banner = NULL;
453 if (!is_wp_text_buffer_started) {
454 is_wp_text_buffer_started = TRUE;
455 wp_text_buffer_library_init ();
460 hildon_program_add_window (hildon_program_get_instance(),
465 multimailbox_get_default_mailbox (const gchar *account_name)
467 gchar *transport_account;
468 gchar *result = NULL;
470 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
472 TNY_ACCOUNT_TYPE_TRANSPORT);
473 if (transport_account) {
475 ModestProtocolRegistry *registry;
477 registry = modest_runtime_get_protocol_registry ();
479 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
480 MODEST_ACCOUNT_PROTO, TRUE);
482 ModestProtocol *protocol =
483 modest_protocol_registry_get_protocol_by_name (registry,
484 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
486 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
487 ModestPairList *pair_list;
489 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
492 ModestPair *pair = (ModestPair *) pair_list->data;
493 result = g_strdup ((const gchar *) pair->first);
494 modest_pair_list_free (pair_list);
505 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
507 static ModestPairList*
508 get_transports (void)
510 GSList *transports = NULL;
512 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
513 GSList *accounts = modest_account_mgr_account_names (account_mgr,
514 TRUE /* only enabled accounts. */);
516 GSList *cursor = accounts;
518 gchar *account_name = cursor->data;
521 gchar *transport_account;
522 gboolean multi_mailbox = FALSE;
523 ModestProtocol *protocol = NULL;
525 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
527 transport_account = modest_account_mgr_get_server_account_name
528 (modest_runtime_get_account_mgr (),
530 TNY_ACCOUNT_TYPE_TRANSPORT);
531 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
532 ModestPairList *pair_list;
533 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
536 transports = g_slist_concat (transports, pair_list);
537 multi_mailbox = TRUE;
542 if (!multi_mailbox) {
543 gchar *from_string = NULL;
545 from_string = modest_account_mgr_get_from_string (account_mgr,
547 if (from_string && account_name) {
548 gchar *name = account_name;
549 ModestPair *pair = modest_pair_new ((gpointer) name,
550 (gpointer) from_string , TRUE);
551 transports = g_slist_prepend (transports, pair);
556 cursor = cursor->next;
558 g_slist_free (accounts); /* only free the accounts, not the elements,
559 * because they are used in the pairlist */
563 static void window_focus (GtkWindow *window,
567 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
571 scroll_drag_timeout (gpointer userdata)
573 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
574 ModestMsgEditWindowPrivate *priv;
576 /* It could happen that the window was already closed */
577 if (!GTK_WIDGET_VISIBLE (win))
580 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
582 correct_scroll_without_drag_check (win, TRUE);
584 priv->scroll_drag_timeout_id = 0;
590 correct_scroll_without_drag_check_idle (gpointer userdata)
592 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
593 ModestMsgEditWindowPrivate *priv;
595 GdkRectangle rectangle;
596 gint offset_min, offset_max;
600 /* It could happen that the window was already closed */
601 if (!GTK_WIDGET_VISIBLE (w))
604 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
606 insert = gtk_text_buffer_get_insert (priv->text_buffer);
607 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
609 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
610 offset_min = priv->msg_body->allocation.y + rectangle.y;
611 offset_max = offset_min + rectangle.height;
613 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
614 offset_min = MAX (offset_min - 48, 0);
615 offset_max = MIN (offset_max + 48, vadj->upper);
617 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
619 priv->correct_scroll_idle = 0;
624 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
626 ModestMsgEditWindowPrivate *priv;
628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
630 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
633 if (priv->correct_scroll_idle > 0) {
637 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
638 (GSourceFunc) correct_scroll_without_drag_check_idle,
644 correct_scroll (ModestMsgEditWindow *w)
646 ModestMsgEditWindowPrivate *priv;
648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
649 if (gtk_grab_get_current () == priv->msg_body) {
650 if (priv->scroll_drag_timeout_id == 0) {
651 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
653 (GSourceFunc) scroll_drag_timeout,
660 correct_scroll_without_drag_check (w, TRUE);
664 text_buffer_end_user_action (GtkTextBuffer *buffer,
665 ModestMsgEditWindow *userdata)
668 correct_scroll (userdata);
672 text_buffer_mark_set (GtkTextBuffer *buffer,
675 ModestMsgEditWindow *userdata)
677 gtk_text_buffer_begin_user_action (buffer);
678 gtk_text_buffer_end_user_action (buffer);
682 cut_clipboard_check (GtkTextView *text_view,
685 GtkTextBuffer *buffer;
687 buffer = gtk_text_view_get_buffer (text_view);
688 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
689 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
694 copy_clipboard_check (GtkTextView *text_view,
697 GtkTextBuffer *buffer;
699 buffer = gtk_text_view_get_buffer (text_view);
700 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
701 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
706 attachment_deleted (ModestAttachmentsView *attachments_view,
709 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
714 body_size_request (GtkWidget *body,
718 /* Make sure the body always get at least 70 pixels */
719 if (req->height < 70)
724 connect_signals (ModestMsgEditWindow *obj)
726 ModestMsgEditWindowPrivate *priv;
728 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
730 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
731 G_CALLBACK (text_buffer_refresh_attributes), obj);
732 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
733 G_CALLBACK (text_buffer_can_undo), obj);
734 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
735 G_CALLBACK (text_buffer_can_redo), obj);
736 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
737 G_CALLBACK (body_changed), obj);
738 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
739 G_CALLBACK (body_insert_text), obj);
740 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
741 G_CALLBACK (body_changed), obj);
742 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
743 G_CALLBACK (text_buffer_end_user_action), obj);
744 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
745 G_CALLBACK (text_buffer_mark_set), obj);
746 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
747 G_CALLBACK (text_buffer_apply_tag), obj);
748 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
749 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
750 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
751 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
752 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
753 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
755 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
756 G_CALLBACK (modest_ui_actions_on_send), obj);
758 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
759 G_CALLBACK (from_field_changed), obj);
761 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
762 G_CALLBACK (msg_body_focus), obj);
763 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
764 G_CALLBACK (msg_body_focus), obj);
765 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
766 G_CALLBACK (body_size_request), obj);
767 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
768 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
769 "changed", G_CALLBACK (recpt_field_changed), obj);
770 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
771 "changed", G_CALLBACK (recpt_field_changed), obj);
772 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
773 "changed", G_CALLBACK (recpt_field_changed), obj);
774 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
775 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
776 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
778 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
779 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
781 priv->clipboard_change_handler_id =
782 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
783 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
784 priv->default_clipboard_change_handler_id =
785 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
786 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
788 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
789 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
790 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
794 init_wp_text_view_style ()
796 static gboolean initialized = FALSE;
799 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
805 init_window (ModestMsgEditWindow *obj)
807 GtkWidget *to_caption, *subject_caption;
808 GtkWidget *main_vbox;
809 ModestMsgEditWindowPrivate *priv;
810 GtkActionGroup *action_group;
811 ModestWindowPrivate *parent_priv;
812 GdkPixbuf *window_icon = NULL;
813 GError *error = NULL;
815 GtkSizeGroup *title_size_group;
816 GtkSizeGroup *value_size_group;
817 GtkWidget *window_box;
818 GtkWidget *window_align;
819 #if (GTK_MINOR_VERSION >= 10)
820 GdkAtom deserialize_type;
822 GtkWidget *from_send_hbox;
823 GtkWidget *send_icon;
824 GtkWidget *attachments_label;
825 GtkWidget *branding_box;
827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
828 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
830 parent_priv->ui_manager = gtk_ui_manager_new();
831 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
832 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
834 /* Add common actions */
835 gtk_action_group_add_actions (action_group,
836 modest_msg_edit_action_entries,
837 G_N_ELEMENTS (modest_msg_edit_action_entries),
839 gtk_action_group_add_actions (action_group,
840 hildon2_msg_edit_action_entries,
841 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
843 gtk_action_group_add_toggle_actions (action_group,
844 modest_msg_edit_toggle_action_entries,
845 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
847 gtk_action_group_add_radio_actions (action_group,
848 modest_msg_edit_alignment_radio_action_entries,
849 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
851 G_CALLBACK (modest_ui_actions_on_change_justify),
853 gtk_action_group_add_radio_actions (action_group,
854 modest_msg_edit_priority_action_entries,
855 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
857 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
859 gtk_action_group_add_radio_actions (action_group,
860 modest_msg_edit_file_format_action_entries,
861 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
862 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
863 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
865 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
866 g_object_unref (action_group);
868 /* Load the UI definition */
869 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
872 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
873 g_clear_error (&error);
876 /* Add accelerators */
877 gtk_window_add_accel_group (GTK_WINDOW (obj),
878 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
880 parent_priv->menubar = NULL;
882 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
883 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
885 /* Note: This ModestPairList* must exist for as long as the picker
886 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
887 * so it can't know how to manage its memory. */
888 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
889 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
891 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
892 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
893 _("mail_va_from"), priv->from_field);
894 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
895 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
896 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
898 priv->to_field = modest_recpt_editor_new ();
899 priv->cc_field = modest_recpt_editor_new ();
900 priv->bcc_field = modest_recpt_editor_new ();
901 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
902 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
903 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
904 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
905 priv->priority_icon = gtk_image_new ();
906 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
907 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
908 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
909 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
910 hildon_entry_set_placeholder ((HildonEntry *) priv->subject_field, _("mail_va_no_subject"));
911 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
912 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
913 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
914 priv->attachments_view = modest_attachments_view_new (NULL);
915 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
916 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
918 priv->header_box = gtk_vbox_new (FALSE, 0);
920 to_caption = _create_addressbook_box
921 (title_size_group, value_size_group,
922 _("mail_va_to"), priv->to_field);
923 priv->cc_caption = _create_addressbook_box
924 (title_size_group, value_size_group,
925 _("mail_va_cc"), priv->cc_field);
926 priv->bcc_caption = _create_addressbook_box
927 (title_size_group, value_size_group,
928 _("mail_va_hotfix1"), priv->bcc_field);
929 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
930 _("mail_va_subject"), FALSE, priv->subject_box);
931 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
932 _("mail_va_attachment"),
934 priv->attachments_view,
935 HILDON_SIZE_AUTO_WIDTH |
936 HILDON_SIZE_AUTO_HEIGHT);
937 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
938 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
941 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
942 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
943 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
944 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
946 g_object_unref (title_size_group);
947 g_object_unref (value_size_group);
949 priv->brand_icon = gtk_image_new ();
950 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
951 priv->brand_label = gtk_label_new (NULL);
952 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
953 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
954 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
955 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
957 from_send_hbox = gtk_hbox_new (FALSE, 0);
958 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
959 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
961 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
962 gtk_widget_show (branding_box);
963 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
964 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
966 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
967 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
968 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
969 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
972 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
973 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
974 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
975 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
976 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
977 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
978 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
979 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
981 init_wp_text_view_style ();
983 priv->msg_body = modest_wp_text_view_new ();
986 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
987 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
988 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
989 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
990 #if (GTK_MINOR_VERSION >= 10)
991 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
992 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
994 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
995 deserialize_type, TRUE);
997 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
999 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1000 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1002 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1004 priv->pannable = hildon_pannable_area_new ();
1006 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1008 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1009 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1010 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1012 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1013 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1014 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1016 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1017 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1019 window_box = gtk_vbox_new (FALSE, 0);
1020 gtk_container_add (GTK_CONTAINER(obj), window_box);
1022 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1024 /* Set window icon */
1025 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1027 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1028 g_object_unref (window_icon);
1033 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1035 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1037 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1038 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1039 priv->clipboard_change_handler_id))
1040 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1041 priv->clipboard_change_handler_id);
1042 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1043 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1044 priv->default_clipboard_change_handler_id))
1045 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1046 priv->default_clipboard_change_handler_id);
1048 if (priv->account_removed_handler_id &&
1049 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1050 priv->account_removed_handler_id))
1051 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1052 priv->account_removed_handler_id);
1056 modest_msg_edit_window_finalize (GObject *obj)
1058 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1060 if (priv->max_chars_banner) {
1061 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1062 priv->max_chars_banner = FALSE;
1065 /* Sanity check: shouldn't be needed, the window mgr should
1066 call this function before */
1067 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1069 if (priv->font_dialog != NULL) {
1070 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1073 if (priv->clipboard_text != NULL) {
1074 g_free (priv->clipboard_text);
1075 priv->clipboard_text = NULL;
1078 if (priv->draft_msg != NULL) {
1079 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1080 if (TNY_IS_HEADER (header)) {
1081 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1082 modest_window_mgr_unregister_header (mgr, header);
1084 g_object_unref (priv->draft_msg);
1085 priv->draft_msg = NULL;
1087 if (priv->outbox_msg != NULL) {
1088 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1089 if (TNY_IS_HEADER (header)) {
1090 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1091 modest_window_mgr_unregister_header (mgr, header);
1093 g_object_unref (priv->outbox_msg);
1094 priv->outbox_msg = NULL;
1096 if (priv->correct_scroll_idle > 0) {
1097 g_source_remove (priv->correct_scroll_idle);
1098 priv->correct_scroll_idle = 0;
1100 if (priv->scroll_drag_timeout_id > 0) {
1101 g_source_remove (priv->scroll_drag_timeout_id);
1102 priv->scroll_drag_timeout_id = 0;
1104 if (priv->clipboard_owner_idle > 0) {
1105 g_source_remove (priv->clipboard_owner_idle);
1106 priv->clipboard_owner_idle = 0;
1108 if (priv->original_account_name)
1109 g_free (priv->original_account_name);
1110 if (priv->original_mailbox)
1111 g_free (priv->original_mailbox);
1112 g_free (priv->msg_uid);
1113 g_free (priv->last_search);
1114 g_free (priv->references);
1115 g_free (priv->in_reply_to);
1116 g_object_unref (priv->attachments);
1117 g_object_unref (priv->images);
1119 /* This had to stay alive for as long as the picker that used it: */
1120 modest_pair_list_free (priv->from_field_protos);
1122 G_OBJECT_CLASS(parent_class)->finalize (obj);
1126 pixbuf_size_prepared (GdkPixbufLoader *loader,
1129 ModestMsgEditWindow *self)
1131 gint new_height, new_width;
1134 new_height = height;
1138 if (width > IMAGE_MAX_WIDTH) {
1139 new_height = height * IMAGE_MAX_WIDTH / width;
1140 new_width = IMAGE_MAX_WIDTH;
1143 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1147 pixbuf_from_stream (TnyStream *stream,
1148 const gchar *mime_type,
1149 guint64 *stream_size,
1150 ModestMsgEditWindow *self)
1152 GdkPixbufLoader *loader;
1155 GError *error = NULL;
1159 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1161 if (loader == NULL) {
1166 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1168 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1170 tny_stream_reset (TNY_STREAM (stream));
1171 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1172 unsigned char read_buffer[128];
1174 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1176 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1179 /* Allow some UI responsiveness */
1180 while (gtk_events_pending ())
1181 gtk_main_iteration ();
1183 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1185 gdk_pixbuf_loader_close (loader, &error);
1188 g_error_free (error);
1189 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1191 g_object_ref (pixbuf);
1192 g_object_unref (loader);
1197 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1198 GdkPixbuf *new_pixbuf;
1200 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1201 gdk_pixbuf_get_width (pixbuf);
1202 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1203 g_object_unref (pixbuf);
1204 pixbuf = new_pixbuf;
1208 *stream_size = size;
1214 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1216 ModestMsgEditWindowPrivate *priv;
1219 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1221 g_object_ref (self);
1222 for (iter = tny_list_create_iterator (attachments);
1223 !tny_iterator_is_done (iter);
1224 tny_iterator_next (iter)) {
1225 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1226 const gchar *cid = tny_mime_part_get_content_id (part);
1227 const gchar *mime_type = tny_mime_part_get_content_type (part);
1228 if ((cid != NULL)&&(mime_type != NULL)) {
1229 guint64 stream_size;
1230 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1231 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1234 g_object_unref (stream);
1236 if (pixbuf != NULL) {
1237 priv->images_count ++;
1238 priv->images_size += stream_size;
1239 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1240 g_object_unref (pixbuf);
1243 g_object_unref (part);
1245 g_object_unref (iter);
1246 g_object_unref (self);
1250 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1252 TnyMimePart *parent = NULL;
1253 const gchar *content_type = NULL;
1254 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1256 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1258 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1259 parent = g_object_ref (msg);
1260 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1261 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1264 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1265 iter = tny_list_create_iterator (parts);
1266 while (!tny_iterator_is_done (iter)) {
1268 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1269 content_type = tny_mime_part_get_content_type (part);
1270 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1274 g_object_unref (part);
1276 tny_iterator_next (iter);
1278 g_object_unref (iter);
1279 g_object_unref (parts);
1282 if (parent != NULL) {
1283 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1286 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1287 iter = tny_list_create_iterator (parts);
1288 while (!tny_iterator_is_done (iter)) {
1290 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1291 content_type = tny_mime_part_get_content_type (part);
1292 if (content_type && g_str_has_prefix (content_type, "image/")) {
1293 tny_list_prepend (priv->images, (GObject *) part);
1295 g_object_unref (part);
1296 tny_iterator_next (iter);
1298 g_object_unref (iter);
1299 g_object_unref (parts);
1300 g_object_unref (parent);
1305 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1308 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1310 for (iter = tny_list_create_iterator (attachments) ;
1311 !tny_iterator_is_done (iter);
1312 tny_iterator_next (iter)) {
1313 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1314 const gchar *cid = tny_mime_part_get_content_id (part);
1316 char *invalid = NULL;
1317 gint int_cid = strtol (cid, &invalid, 10);
1318 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1319 priv->next_cid = int_cid + 1;
1322 g_object_unref (part);
1324 g_object_unref (iter);
1328 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1331 gchar *to, *cc, *bcc, *subject;
1333 ModestMsgEditWindowPrivate *priv;
1334 ModestWindowPrivate *parent_priv;
1336 TnyHeaderFlags priority_flags;
1337 TnyFolder *msg_folder;
1338 gboolean is_html = FALSE;
1339 gboolean field_view_set;
1341 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1342 g_return_if_fail (TNY_IS_MSG (msg));
1344 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1345 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1347 header = tny_msg_get_header (msg);
1348 to = tny_header_dup_to (header);
1349 cc = tny_header_dup_cc (header);
1350 bcc = tny_header_dup_bcc (header);
1351 subject = tny_header_dup_subject (header);
1353 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1354 priority_flags = tny_header_get_priority (header);
1357 gchar *quoted_names = modest_text_utils_quote_names (to);
1358 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1359 g_free (quoted_names);
1362 field_view_set = TRUE;
1364 gchar *quoted_names = modest_text_utils_quote_names (cc);
1365 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1366 g_free (quoted_names);
1367 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1368 gtk_widget_show (priv->cc_caption);
1369 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1370 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1371 gtk_widget_hide (priv->cc_caption);
1372 field_view_set = FALSE;
1374 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1376 field_view_set = TRUE;
1378 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1379 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1380 g_free (quoted_names);
1381 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1382 gtk_widget_show (priv->bcc_caption);
1383 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1384 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1385 gtk_widget_hide (priv->bcc_caption);
1386 field_view_set = FALSE;
1388 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1392 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1393 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1396 update_window_title (self);
1398 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1399 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1401 if ((body == NULL)||(body[0] == '\0')) {
1403 body = modest_text_utils_convert_to_html ("");
1406 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1407 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1410 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1413 /* Add attachments to the view */
1414 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1415 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1416 if (tny_list_get_length (priv->attachments) == 0) {
1417 gtk_widget_hide (priv->attachments_caption);
1419 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1420 gtk_widget_show_all (priv->attachments_caption);
1422 get_related_images (self, msg);
1423 update_next_cid (self, priv->attachments);
1424 update_next_cid (self, priv->images);
1425 replace_with_images (self, priv->images);
1427 if (preserve_is_rich && !is_html) {
1428 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1429 /* Get the default format required from configuration */
1430 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1431 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1434 /* Set the default focus depending on having already a To: field or not */
1435 if ((!to)||(*to == '\0')) {
1436 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1438 gtk_widget_grab_focus (priv->msg_body);
1441 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1443 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1444 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1446 modest_msg_edit_window_set_modified (self, FALSE);
1448 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1449 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1450 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1451 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1453 if (priv->msg_uid) {
1454 g_free (priv->msg_uid);
1455 priv->msg_uid = NULL;
1458 /* we should set a reference to the incoming message if it is a draft */
1459 msg_folder = tny_msg_get_folder (msg);
1461 if (modest_tny_folder_is_local_folder (msg_folder)) {
1462 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1463 if (type == TNY_FOLDER_TYPE_INVALID)
1464 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1466 if (type == TNY_FOLDER_TYPE_DRAFTS)
1467 priv->draft_msg = g_object_ref(msg);
1468 if (type == TNY_FOLDER_TYPE_OUTBOX)
1469 priv->outbox_msg = g_object_ref(msg);
1470 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1472 g_object_unref (msg_folder);
1483 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1485 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1486 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1487 GtkWidget *placeholder;
1488 GtkWidget *tool_item;
1493 GtkWidget *sizes_menu;
1494 GtkWidget *fonts_menu;
1500 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1501 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1502 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1503 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1505 /* Font color placeholder */
1506 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1507 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1510 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1511 priv->font_color_button = hildon_color_button_new ();
1512 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1513 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1514 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1515 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1516 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1517 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1518 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1519 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1521 G_CALLBACK (modest_msg_edit_window_color_button_change),
1524 /* Font size and face placeholder */
1525 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1526 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1528 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1529 priv->size_tool_button_label = gtk_label_new (NULL);
1530 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1531 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1532 size_text, "</span>", NULL);
1533 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1534 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1536 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1537 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1538 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1539 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1540 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1541 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1542 gtk_widget_set_sensitive (arrow, FALSE);
1543 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1544 sizes_menu = gtk_menu_new ();
1545 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1546 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1549 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1550 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1552 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1556 if (wp_font_size[size_index] == 12)
1557 priv->current_size_index = size_index;
1561 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1562 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1563 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1564 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1565 priv->font_size_toolitem = tool_item;
1568 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1569 priv->font_tool_button_label = gtk_label_new (NULL);
1570 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1571 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1572 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1574 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1575 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1576 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1577 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1578 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1579 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1580 gtk_widget_set_sensitive (arrow, FALSE);
1581 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1582 fonts_menu = gtk_menu_new ();
1583 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1584 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1587 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1589 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1590 0, wp_get_font_name (font_index),
1593 if (font_index == DEFAULT_FONT)
1594 priv->current_face_index = font_index;
1596 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1597 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1598 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1599 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1600 priv->font_face_toolitem = tool_item;
1602 /* Set expand and homogeneous for remaining items */
1603 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1604 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1605 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1606 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1607 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1608 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1610 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1611 will not show the tool items added to the placeholders) */
1612 gtk_widget_show_all (parent_priv->toolbar);
1614 /* Set the no show all *after* showing all items. We do not
1615 want the toolbar to be shown with a show all because it
1616 could go agains the gconf setting regarding showing or not
1617 the toolbar of the editor window */
1618 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1624 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1627 ModestWindowPrivate *parent_priv;
1628 ModestMsgEditWindowPrivate *priv;
1629 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1630 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1631 ModestWindowMgr *mgr = NULL;
1633 g_return_val_if_fail (msg, NULL);
1634 g_return_val_if_fail (account_name, NULL);
1636 mgr = modest_runtime_get_window_mgr ();
1638 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1640 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1641 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1643 /* Menubar. Update the state of some toggles */
1644 priv->from_field_protos = get_transports ();
1645 priv->original_mailbox = NULL;
1646 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1647 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1648 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1649 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1650 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1651 priv->original_mailbox = g_strdup (mailbox);
1652 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1653 /* We set the first mailbox as the active mailbox */
1654 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1655 if (priv->original_mailbox != NULL)
1656 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1657 (gpointer) priv->original_mailbox);
1659 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1660 (gpointer) account_name);
1662 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1664 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1665 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1666 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1668 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1669 hildon_touch_selector_get_current_text
1670 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1671 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1672 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1675 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1677 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1679 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1680 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1682 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1684 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1685 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1686 /* Add common dimming rules */
1687 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1688 modest_msg_edit_window_toolbar_dimming_entries,
1689 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1690 MODEST_WINDOW (obj));
1691 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1692 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1693 MODEST_WINDOW (obj));
1694 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1695 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1696 MODEST_WINDOW (obj));
1697 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1698 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1699 MODEST_WINDOW (obj));
1700 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1701 G_CALLBACK (modest_ui_dimming_rules_on_send),
1702 MODEST_WINDOW (obj));
1703 /* Insert dimming rules group for this window */
1704 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1705 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1707 /* Setup app menu */
1708 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1710 /* Checks the dimming rules */
1711 g_object_unref (toolbar_rules_group);
1712 g_object_unref (clipboard_rules_group);
1713 gtk_widget_hide (priv->priority_icon);
1714 gtk_widget_queue_resize (priv->subject_box);
1715 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1717 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1719 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1720 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1721 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1722 priv->update_caption_visibility = TRUE;
1724 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1726 /* Track account-removed signal, this window should be closed
1727 in the case we're creating a mail associated to the account
1729 priv->account_removed_handler_id =
1730 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1732 G_CALLBACK(on_account_removed),
1735 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1737 return (ModestWindow*) obj;
1741 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1743 GString **string_buffer = (GString **) user_data;
1745 *string_buffer = g_string_append (*string_buffer, buffer);
1751 * @result: A new string which should be freed with g_free().
1754 get_formatted_data (ModestMsgEditWindow *edit_window)
1756 ModestMsgEditWindowPrivate *priv;
1757 GString *string_buffer = g_string_new ("");
1759 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1761 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1763 modest_text_utils_hyperlinkify (string_buffer);
1765 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1767 return g_string_free (string_buffer, FALSE);
1772 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1775 const gchar *account_name;
1776 ModestMsgEditWindowPrivate *priv;
1777 TnyIterator *att_iter;
1778 const gchar *picker_active_id;
1780 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1782 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1784 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1785 g_return_val_if_fail (picker_active_id, NULL);
1786 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1788 /* don't free these (except from) */
1789 data = g_slice_new0 (MsgData);
1790 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1791 data->account_name = g_strdup (account_name);
1792 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1793 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1794 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1795 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1796 data->references = g_strdup (priv->references);
1797 data->in_reply_to = g_strdup (priv->in_reply_to);
1798 if (priv->draft_msg) {
1799 data->draft_msg = g_object_ref (priv->draft_msg);
1800 } else if (priv->outbox_msg) {
1801 data->draft_msg = g_object_ref (priv->outbox_msg);
1803 data->draft_msg = NULL;
1806 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1808 gtk_text_buffer_get_bounds (buf, &b, &e);
1809 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1811 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1812 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1814 data->html_body = NULL;
1816 /* deep-copy the data */
1817 att_iter = tny_list_create_iterator (priv->attachments);
1818 data->attachments = NULL;
1819 while (!tny_iterator_is_done (att_iter)) {
1820 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1821 if (!(TNY_IS_MIME_PART(part))) {
1822 g_warning ("strange data in attachment list");
1823 g_object_unref (part);
1824 tny_iterator_next (att_iter);
1827 data->attachments = g_list_append (data->attachments,
1829 tny_iterator_next (att_iter);
1831 g_object_unref (att_iter);
1833 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1834 att_iter = tny_list_create_iterator (priv->images);
1835 data->images = NULL;
1836 while (!tny_iterator_is_done (att_iter)) {
1837 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1839 if (!(TNY_IS_MIME_PART(part))) {
1840 g_warning ("strange data in attachment list");
1841 g_object_unref (part);
1842 tny_iterator_next (att_iter);
1845 cid = tny_mime_part_get_content_id (part);
1847 gchar *image_tag_id;
1848 GtkTextTag *image_tag;
1850 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1851 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1852 g_free (image_tag_id);
1854 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1856 ((gtk_text_iter_has_tag (&iter, image_tag))||
1857 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1858 data->images = g_list_append (data->images,
1859 g_object_ref (part));
1861 g_object_unref (part);
1862 tny_iterator_next (att_iter);
1864 g_object_unref (att_iter);
1866 data->priority_flags = priv->priority_flags;
1873 unref_gobject (GObject *obj, gpointer data)
1875 if (!G_IS_OBJECT(obj))
1877 g_object_unref (obj);
1881 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1892 g_free (data->from);
1893 g_free (data->subject);
1894 g_free (data->plain_body);
1895 g_free (data->html_body);
1896 g_free (data->account_name);
1897 g_free (data->references);
1898 g_free (data->in_reply_to);
1900 if (data->draft_msg != NULL) {
1901 g_object_unref (data->draft_msg);
1902 data->draft_msg = NULL;
1905 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1906 g_list_free (data->attachments);
1907 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1908 g_list_free (data->images);
1910 g_slice_free (MsgData, data);
1914 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1916 guint64 *parts_size)
1918 ModestMsgEditWindowPrivate *priv;
1920 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1922 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1924 /* TODO: add images */
1925 *parts_size += priv->images_size;
1926 *parts_count += priv->images_count;
1931 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1934 ModestMsgEditWindowPrivate *priv = NULL;
1935 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1937 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1939 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1941 return MODEST_MSG_EDIT_FORMAT_HTML;
1943 return MODEST_MSG_EDIT_FORMAT_TEXT;
1947 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1948 ModestMsgEditFormat format)
1950 ModestMsgEditWindowPrivate *priv;
1951 ModestWindowPrivate *parent_priv;
1953 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1955 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1958 case MODEST_MSG_EDIT_FORMAT_HTML:
1959 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1960 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1962 case MODEST_MSG_EDIT_FORMAT_TEXT:
1963 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1964 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1967 g_return_if_reached ();
1971 ModestMsgEditFormatState *
1972 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1974 ModestMsgEditFormatState *format_state = NULL;
1975 ModestMsgEditWindowPrivate *priv;
1976 WPTextBufferFormat *buffer_format;
1978 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1980 buffer_format = g_new0 (WPTextBufferFormat, 1);
1981 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1983 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1985 format_state = g_new0 (ModestMsgEditFormatState, 1);
1986 format_state->bold = buffer_format->bold&0x1;
1987 format_state->italics = buffer_format->italic&0x1;
1988 format_state->bullet = buffer_format->bullet&0x1;
1989 format_state->color = buffer_format->color;
1990 format_state->font_size = buffer_format->font_size;
1991 format_state->font_family = wp_get_font_name (buffer_format->font);
1992 format_state->justification = buffer_format->justification;
1993 g_free (buffer_format);
1995 return format_state;
2000 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2001 const ModestMsgEditFormatState *format_state)
2003 ModestMsgEditWindowPrivate *priv;
2004 WPTextBufferFormat *buffer_format;
2005 WPTextBufferFormat *current_format;
2007 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2008 g_return_if_fail (format_state != NULL);
2010 buffer_format = g_new0 (WPTextBufferFormat, 1);
2011 current_format = g_new0 (WPTextBufferFormat, 1);
2013 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2014 gtk_widget_grab_focus (priv->msg_body);
2015 buffer_format->bold = (format_state->bold != FALSE);
2016 buffer_format->italic = (format_state->italics != FALSE);
2017 buffer_format->color = format_state->color;
2018 buffer_format->font_size = format_state->font_size;
2019 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2020 buffer_format->justification = format_state->justification;
2021 buffer_format->bullet = format_state->bullet;
2023 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2025 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2026 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2027 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2028 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2029 buffer_format->cs.font = (buffer_format->font != current_format->font);
2030 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2031 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2033 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2034 if (buffer_format->cs.bold) {
2035 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2036 GINT_TO_POINTER (buffer_format->bold&0x1));
2038 if (buffer_format->cs.italic) {
2039 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2040 GINT_TO_POINTER (buffer_format->italic&0x1));
2042 if (buffer_format->cs.color) {
2043 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2044 GINT_TO_POINTER (&(buffer_format->color)));
2046 if (buffer_format->cs.font_size) {
2047 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2048 GINT_TO_POINTER (buffer_format->font_size));
2050 if (buffer_format->cs.justification) {
2051 switch (buffer_format->justification) {
2052 case GTK_JUSTIFY_LEFT:
2053 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2054 GINT_TO_POINTER(TRUE));
2056 case GTK_JUSTIFY_CENTER:
2057 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2058 GINT_TO_POINTER(TRUE));
2060 case GTK_JUSTIFY_RIGHT:
2061 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2062 GINT_TO_POINTER(TRUE));
2069 if (buffer_format->cs.font) {
2070 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2071 GINT_TO_POINTER (buffer_format->font));
2073 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2074 if (buffer_format->cs.bullet) {
2075 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2076 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2078 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2080 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2082 g_free (buffer_format);
2083 g_free (current_format);
2085 /* Check dimming rules */
2086 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2087 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2091 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2093 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2095 ModestWindowPrivate *parent_priv;
2096 ModestMsgEditWindowPrivate *priv;
2098 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2101 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2102 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2103 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2104 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2106 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2107 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2108 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2111 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2113 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2114 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2116 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2117 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2119 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2120 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2123 switch (buffer_format->justification)
2125 case GTK_JUSTIFY_LEFT:
2126 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2128 case GTK_JUSTIFY_CENTER:
2129 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2131 case GTK_JUSTIFY_RIGHT:
2132 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2139 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2141 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2142 G_CALLBACK (modest_msg_edit_window_color_button_change),
2144 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2145 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2146 G_CALLBACK (modest_msg_edit_window_color_button_change),
2149 if (priv->current_size_index != buffer_format->font_size) {
2153 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2154 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2158 priv->current_size_index = buffer_format->font_size;
2160 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2161 markup = g_strconcat ("<span font_family='Sans'>",
2162 size_text, "</span>", NULL);
2164 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2168 gtk_tree_path_free (path);
2171 if (priv->current_face_index != buffer_format->font) {
2175 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2176 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2180 priv->current_face_index = buffer_format->font;
2181 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2182 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2183 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2190 g_free (buffer_format);
2196 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2199 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2200 ModestMsgEditWindowPrivate *priv;
2201 GtkWidget *dialog = NULL;
2203 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2204 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2206 dialog = hildon_color_chooser_new ();
2207 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2208 g_free (buffer_format);
2210 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2212 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2213 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2216 gtk_widget_destroy (dialog);
2221 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2224 ModestMsgEditWindowPrivate *priv;
2225 GtkWidget *dialog = NULL;
2226 GdkColor *old_color = NULL;
2228 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2229 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2231 dialog = hildon_color_chooser_new ();
2232 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2234 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2236 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2237 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2239 gtk_widget_destroy (dialog);
2244 create_stream_for_uri (const gchar* uri)
2249 TnyStream *result = NULL;
2251 GnomeVFSHandle *handle = NULL;
2252 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2253 if (test == GNOME_VFS_OK) {
2254 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2255 /* Streams over OBEX (Bluetooth) are not seekable but
2256 * we expect them to be (we might need to read them
2257 * several times). So if this is a Bluetooth URI just
2258 * read the whole file into memory (this is not a fast
2259 * protocol so we can assume that these files are not
2260 * going to be very big) */
2261 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2262 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2263 TnyStream *memstream = tny_camel_mem_stream_new ();
2264 tny_stream_write_to_stream (vfssstream, memstream);
2265 g_object_unref (vfssstream);
2268 result = vfssstream;
2276 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2279 ModestMsgEditWindowPrivate *priv;
2280 GtkWidget *dialog = NULL;
2282 GSList *uris = NULL;
2283 GSList *uri_node = NULL;
2285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2287 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2288 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2289 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2291 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2293 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2294 GTK_WINDOW (dialog), GTK_WINDOW (window));
2296 response = gtk_dialog_run (GTK_DIALOG (dialog));
2298 case GTK_RESPONSE_OK:
2300 gchar *current_folder;
2301 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2302 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2303 if (current_folder && current_folder != '\0') {
2305 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2306 current_folder, &err);
2308 g_debug ("Error storing latest used folder: %s", err->message);
2312 g_free (current_folder);
2318 gtk_widget_destroy (dialog);
2320 g_object_ref (window);
2321 /* The operation could take some time so allow the dialog to be closed */
2322 while (gtk_events_pending ())
2323 gtk_main_iteration ();
2325 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2327 GnomeVFSHandle *handle = NULL;
2328 GnomeVFSResult result;
2329 GtkTextIter position;
2330 GtkTextMark *insert_mark;
2332 uri = (const gchar *) uri_node->data;
2333 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2334 if (result == GNOME_VFS_OK) {
2336 GnomeVFSFileInfo *info;
2337 gchar *filename, *basename, *escaped_filename;
2338 TnyMimePart *mime_part;
2340 const gchar *mime_type = NULL;
2341 GnomeVFSURI *vfs_uri;
2342 guint64 stream_size;
2344 gnome_vfs_close (handle);
2345 vfs_uri = gnome_vfs_uri_new (uri);
2347 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2348 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2349 g_free (escaped_filename);
2350 gnome_vfs_uri_unref (vfs_uri);
2351 info = gnome_vfs_file_info_new ();
2353 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2354 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2356 mime_type = gnome_vfs_file_info_get_mime_type (info);
2358 mime_part = tny_platform_factory_new_mime_part
2359 (modest_runtime_get_platform_factory ());
2361 TnyStream *stream = create_stream_for_uri (uri);
2363 if (stream == NULL) {
2365 modest_platform_information_banner (NULL, NULL,
2366 _FM("sfil_ib_opening_not_allowed"));
2368 g_object_unref (mime_part);
2369 gnome_vfs_file_info_unref (info);
2373 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2375 content_id = g_strdup_printf ("%d", priv->next_cid);
2376 tny_mime_part_set_content_id (mime_part, content_id);
2377 g_free (content_id);
2380 basename = g_path_get_basename (filename);
2381 tny_mime_part_set_filename (mime_part, basename);
2384 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2386 if (pixbuf != NULL) {
2387 priv->images_size += stream_size;
2388 priv->images_count ++;
2389 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2390 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2391 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2392 tny_mime_part_get_content_id (mime_part), pixbuf);
2393 g_object_unref (pixbuf);
2395 tny_list_prepend (priv->images, (GObject *) mime_part);
2396 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2398 modest_platform_information_banner (NULL, NULL,
2399 _("mail_ib_file_operation_failed"));
2403 g_object_unref (mime_part);
2404 gnome_vfs_file_info_unref (info);
2408 g_object_unref (window);
2412 on_attach_file_response (GtkDialog *dialog,
2416 GSList *uris = NULL;
2418 GnomeVFSFileSize total_size, allowed_size;
2419 ModestMsgEditWindow *window;
2420 ModestMsgEditWindowPrivate *priv;
2425 case GTK_RESPONSE_OK:
2427 gchar *current_folder;
2429 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2430 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2431 if (current_folder && current_folder != '\0') {
2433 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2434 current_folder, &err);
2436 g_debug ("Error storing latest used folder: %s", err->message);
2440 g_free (current_folder);
2447 window = MODEST_MSG_EDIT_WINDOW (user_data);
2448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2450 /* allowed size is the maximum size - what's already there */
2451 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2452 &att_num, &att_size);
2453 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2456 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2458 const gchar *uri = (const gchar *) uri_node->data;
2461 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2463 if (total_size > allowed_size) {
2464 g_debug ("%s: total size: %u",
2465 __FUNCTION__, (unsigned int)total_size);
2468 allowed_size -= total_size;
2470 g_slist_foreach (uris, (GFunc) g_free, NULL);
2471 g_slist_free (uris);
2473 gtk_widget_destroy (GTK_WIDGET (dialog));
2477 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2479 GtkWidget *dialog = NULL;
2480 ModestMsgEditWindowPrivate *priv;
2483 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2487 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2490 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2491 GTK_FILE_CHOOSER_ACTION_OPEN);
2492 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2493 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2494 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2495 if (conf_folder && conf_folder[0] != '\0') {
2496 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2499 /* Set the default folder to documents folder */
2500 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2503 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2504 ".documents", NULL);
2506 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2507 g_free (docs_folder);
2509 g_free (conf_folder);
2510 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2511 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2512 GTK_WINDOW (dialog), GTK_WINDOW (window));
2514 /* Connect to response & show */
2515 g_signal_connect (dialog, "response",
2516 G_CALLBACK (on_attach_file_response), window);
2517 gtk_widget_show (dialog);
2522 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2524 GnomeVFSFileSize allowed_size)
2527 GnomeVFSHandle *handle = NULL;
2528 ModestMsgEditWindowPrivate *priv;
2529 GnomeVFSResult result;
2530 GnomeVFSFileSize size = 0;
2531 g_return_val_if_fail (window, 0);
2532 g_return_val_if_fail (uri, 0);
2534 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2536 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2537 if (result == GNOME_VFS_OK) {
2538 TnyMimePart *mime_part;
2540 const gchar *mime_type = NULL;
2542 gchar *escaped_filename;
2545 GnomeVFSFileInfo *info;
2546 GnomeVFSURI *vfs_uri;
2548 gnome_vfs_close (handle);
2549 vfs_uri = gnome_vfs_uri_new (uri);
2552 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2553 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2554 g_free (escaped_filename);
2555 gnome_vfs_uri_unref (vfs_uri);
2557 info = gnome_vfs_file_info_new ();
2559 if (gnome_vfs_get_file_info (uri,
2561 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2563 mime_type = gnome_vfs_file_info_get_mime_type (info);
2564 mime_part = tny_platform_factory_new_mime_part
2565 (modest_runtime_get_platform_factory ());
2567 /* try to get the attachment's size; this may fail for weird
2568 * file systems, like obex, upnp... */
2569 if (allowed_size != 0 &&
2570 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2572 if (size > allowed_size) {
2573 modest_platform_information_banner (NULL, NULL,
2574 _("mail_ib_error_attachment_size"));
2579 g_debug ("%s: could not get attachment size", __FUNCTION__);
2581 stream = create_stream_for_uri (uri);
2583 if (stream == NULL) {
2585 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2587 g_object_unref (mime_part);
2589 gnome_vfs_file_info_unref (info);
2593 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2594 g_object_unref (stream);
2596 content_id = g_strdup_printf ("%d", priv->next_cid);
2597 tny_mime_part_set_content_id (mime_part, content_id);
2598 g_free (content_id);
2601 basename = g_path_get_basename (filename);
2602 tny_mime_part_set_filename (mime_part, basename);
2605 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2606 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2608 info->size == 0, info->size);
2609 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2610 gtk_widget_show_all (priv->attachments_caption);
2611 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2613 g_object_unref (mime_part);
2614 gnome_vfs_file_info_unref (info);
2621 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2624 ModestMsgEditWindowPrivate *priv;
2627 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2628 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2630 if (att_list == NULL) {
2631 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2632 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2633 g_object_unref (att_list);
2637 g_object_ref (att_list);
2640 if (tny_list_get_length (att_list) == 0) {
2641 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2643 gboolean dialog_response;
2644 gchar *message = NULL;
2645 gchar *filename = NULL;
2647 if (tny_list_get_length (att_list) == 1) {
2649 iter = tny_list_create_iterator (att_list);
2650 part = (TnyMimePart *) tny_iterator_get_current (iter);
2651 g_object_unref (iter);
2652 if (TNY_IS_MSG (part)) {
2653 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2655 filename = tny_header_dup_subject (header);
2656 g_object_unref (header);
2658 if (filename == NULL) {
2659 filename = g_strdup (_("mail_va_no_subject"));
2662 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2664 g_object_unref (part);
2666 filename = g_strdup ("");
2668 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2669 "emev_nc_delete_attachments",
2670 tny_list_get_length (att_list)), filename);
2673 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2677 if (dialog_response != GTK_RESPONSE_OK) {
2678 g_object_unref (att_list);
2682 for (iter = tny_list_create_iterator (att_list);
2683 !tny_iterator_is_done (iter);
2684 tny_iterator_next (iter)) {
2685 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2686 const gchar *att_id;
2687 tny_list_remove (priv->attachments, (GObject *) mime_part);
2689 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2691 if (tny_list_get_length (priv->attachments) == 0)
2692 gtk_widget_hide (priv->attachments_caption);
2693 att_id = tny_mime_part_get_content_id (mime_part);
2695 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2697 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2698 g_object_unref (mime_part);
2700 g_object_unref (iter);
2703 g_object_unref (att_list);
2705 /* if the last attachment has been removed, focus the Subject: field */
2706 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2707 gtk_widget_grab_focus (priv->subject_field);
2711 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2714 ModestMsgEditWindowPrivate *priv;
2717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2719 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &new_color);
2721 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) &new_color);
2723 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2727 font_size_clicked (GtkToolButton *button,
2728 ModestMsgEditWindow *window)
2730 ModestMsgEditWindowPrivate *priv;
2731 GtkWidget *selector, *dialog;
2733 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2735 selector = hildon_touch_selector_new ();
2736 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2737 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2739 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2740 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2741 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2743 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2747 WPTextBufferFormat format;
2749 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2751 memset (&format, 0, sizeof (format));
2752 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2754 format.cs.font_size = TRUE;
2755 format.cs.text_position = TRUE;
2756 format.cs.font = TRUE;
2757 format.font_size = new_index;
2758 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2760 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2761 GINT_TO_POINTER (new_index)))
2762 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2764 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2765 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2766 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2767 size_text, "</span>", NULL);
2769 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2773 gtk_widget_destroy (dialog);
2775 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2780 font_face_clicked (GtkToolButton *button,
2781 ModestMsgEditWindow *window)
2783 ModestMsgEditWindowPrivate *priv;
2784 GtkWidget *selector, *dialog;
2785 GtkCellRenderer *renderer;
2787 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2789 selector = hildon_touch_selector_new ();
2790 renderer = gtk_cell_renderer_text_new ();
2791 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2792 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2793 renderer, "family", 0, "text", 0, NULL);
2794 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2796 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2797 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2798 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2800 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2801 gint new_font_index;
2805 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2806 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2807 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2811 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2813 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2814 GINT_TO_POINTER(new_font_index)))
2815 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2817 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2818 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2820 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2824 gtk_tree_path_free (path);
2827 gtk_widget_destroy (dialog);
2829 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2834 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2837 ModestMsgEditWindowPrivate *priv = NULL;
2838 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2840 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2841 if (!priv->update_caption_visibility)
2844 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2846 gtk_widget_show (priv->cc_caption);
2848 gtk_widget_hide (priv->cc_caption);
2850 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2854 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2857 ModestMsgEditWindowPrivate *priv = NULL;
2858 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2861 if (!priv->update_caption_visibility)
2864 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2866 gtk_widget_show (priv->bcc_caption);
2868 gtk_widget_hide (priv->bcc_caption);
2870 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2874 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2875 ModestRecptEditor *editor)
2877 ModestMsgEditWindowPrivate *priv;
2879 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2880 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2882 /* we check for low-mem; in that case, show a warning, and don't allow
2883 * for the addressbook
2885 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2888 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2890 if (editor == NULL) {
2891 GtkWidget *view_focus, *parent;
2892 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2894 /* This code should be kept in sync with ModestRecptEditor. The
2895 textview inside the recpt editor is the one that really gets the
2896 focus. As it's inside a scrolled window, and this one inside the
2897 hbox recpt editor inherits from, we'll need to go up in the
2898 hierarchy to know if the text view is part of the recpt editor
2899 or if it's a different text entry */
2900 parent = gtk_widget_get_parent (view_focus);
2901 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2902 editor = MODEST_RECPT_EDITOR (parent);
2905 editor = MODEST_RECPT_EDITOR (priv->to_field);
2908 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2912 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2914 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2916 modest_msg_edit_window_open_addressbook (window, NULL);
2920 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2921 gboolean show_toolbar)
2923 ModestWindowPrivate *parent_priv;
2924 ModestMsgEditWindowPrivate *priv;
2926 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2927 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2928 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2930 /* We can not just use the code of
2931 modest_msg_edit_window_setup_toolbar because it has a
2932 mixture of both initialization and creation code. */
2934 gint current_format;
2935 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2936 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2937 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2938 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2940 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2943 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2948 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2949 TnyHeaderFlags priority_flags)
2951 ModestMsgEditWindowPrivate *priv;
2952 ModestWindowPrivate *parent_priv;
2954 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2956 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2957 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2959 if (priv->priority_flags != priority_flags) {
2960 GtkAction *priority_action = NULL;
2962 priv->priority_flags = priority_flags;
2964 switch (priority_flags) {
2965 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2966 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2967 MODEST_HEADER_ICON_HIGH,
2968 HILDON_ICON_SIZE_SMALL);
2969 gtk_widget_show (priv->priority_icon);
2970 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2971 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2973 case TNY_HEADER_FLAG_LOW_PRIORITY:
2974 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2975 MODEST_HEADER_ICON_LOW,
2976 HILDON_ICON_SIZE_SMALL);
2977 gtk_widget_show (priv->priority_icon);
2978 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2979 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2982 gtk_widget_hide (priv->priority_icon);
2983 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2984 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2987 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2988 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2990 gtk_widget_queue_resize (priv->subject_box);
2994 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2997 ModestMsgEditWindowPrivate *priv;
2998 ModestWindowPrivate *parent_priv;
2999 gint current_format;
3001 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3003 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3004 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3006 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3007 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3009 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3011 if (current_format != file_format) {
3012 switch (file_format) {
3013 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3014 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3015 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3016 if (parent_priv->toolbar)
3017 gtk_widget_show (parent_priv->toolbar);
3019 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3023 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3024 response = gtk_dialog_run (GTK_DIALOG (dialog));
3025 gtk_widget_destroy (dialog);
3026 if (response == GTK_RESPONSE_OK) {
3027 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3028 if (parent_priv->toolbar)
3029 gtk_widget_hide (parent_priv->toolbar);
3031 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3032 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3037 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3038 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3039 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3044 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3047 ModestMsgEditWindowPrivate *priv;
3048 WPTextBufferFormat oldfmt, fmt;
3049 gint old_position = 0;
3053 GdkColor *color = NULL;
3054 gboolean bold, bold_set, italic, italic_set;
3055 gboolean underline, underline_set;
3056 gboolean strikethrough, strikethrough_set;
3057 gboolean position_set;
3058 gboolean font_size_set, font_set, color_set;
3061 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3064 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3065 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3066 GTK_WINDOW(dialog), GTK_WINDOW (window));
3068 /* First we get the currently selected font information */
3069 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3071 switch (oldfmt.text_position) {
3072 case TEXT_POSITION_NORMAL:
3075 case TEXT_POSITION_SUPERSCRIPT:
3083 g_object_set (G_OBJECT (dialog),
3084 "bold", oldfmt.bold != FALSE,
3085 "bold-set", !oldfmt.cs.bold,
3086 "underline", oldfmt.underline != FALSE,
3087 "underline-set", !oldfmt.cs.underline,
3088 "italic", oldfmt.italic != FALSE,
3089 "italic-set", !oldfmt.cs.italic,
3090 "strikethrough", oldfmt.strikethrough != FALSE,
3091 "strikethrough-set", !oldfmt.cs.strikethrough,
3092 "color", &oldfmt.color,
3093 "color-set", !oldfmt.cs.color,
3094 "size", wp_font_size[oldfmt.font_size],
3095 "size-set", !oldfmt.cs.font_size,
3096 "position", old_position,
3097 "position-set", !oldfmt.cs.text_position,
3098 "family", wp_get_font_name (oldfmt.font),
3099 "family-set", !oldfmt.cs.font,
3102 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3103 GTK_WINDOW (dialog), GTK_WINDOW (window));
3104 gtk_widget_show_all (dialog);
3105 priv->font_dialog = dialog;
3106 response = gtk_dialog_run (GTK_DIALOG (dialog));
3107 priv->font_dialog = NULL;
3108 if (response == GTK_RESPONSE_OK) {
3110 g_object_get( dialog,
3112 "bold-set", &bold_set,
3113 "underline", &underline,
3114 "underline-set", &underline_set,
3116 "italic-set", &italic_set,
3117 "strikethrough", &strikethrough,
3118 "strikethrough-set", &strikethrough_set,
3120 "color-set", &color_set,
3122 "size-set", &font_size_set,
3123 "family", &font_name,
3124 "family-set", &font_set,
3125 "position", &position,
3126 "position-set", &position_set,
3131 if (response == GTK_RESPONSE_OK) {
3132 memset(&fmt, 0, sizeof(fmt));
3138 fmt.italic = italic;
3139 fmt.cs.italic = TRUE;
3141 if (underline_set) {
3142 fmt.underline = underline;
3143 fmt.cs.underline = TRUE;
3145 if (strikethrough_set) {
3146 fmt.strikethrough = strikethrough;
3147 fmt.cs.strikethrough = TRUE;
3152 ? TEXT_POSITION_NORMAL
3153 : ( ( position == 1 )
3154 ? TEXT_POSITION_SUPERSCRIPT
3155 : TEXT_POSITION_SUBSCRIPT );
3156 fmt.cs.text_position = TRUE;
3157 fmt.font_size = oldfmt.font_size;
3161 fmt.cs.color = TRUE;
3164 fmt.font = wp_get_font_index(font_name,
3169 if (font_size_set) {
3170 fmt.cs.font_size = TRUE;
3171 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3173 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3174 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3176 gtk_widget_destroy (dialog);
3178 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3182 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3184 ModestMsgEditWindowPrivate *priv;
3185 ModestWindowPrivate *parent_priv;
3186 gboolean was_rich_text, is_rich_text;
3188 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3189 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3190 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3192 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3194 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3196 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3198 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3200 gtk_widget_show (parent_priv->toolbar);
3202 gtk_widget_hide (parent_priv->toolbar);
3205 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3206 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3210 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3212 ModestMsgEditWindowPrivate *priv;
3214 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3215 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3217 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3219 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3220 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3225 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3227 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3229 priv->can_undo = can_undo;
3233 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3235 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3237 priv->can_redo = can_redo;
3241 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3243 ModestMsgEditWindowPrivate *priv;
3244 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3245 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3247 return priv->can_undo;
3251 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3253 ModestMsgEditWindowPrivate *priv;
3254 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3255 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3257 return priv->can_redo;
3262 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3265 GtkTextIter match_start, match_end;
3267 if (image_id == NULL)
3270 gtk_text_buffer_get_start_iter (buffer, &iter);
3272 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3273 GSList *tags = gtk_text_iter_get_tags (&match_start);
3275 for (node = tags; node != NULL; node = g_slist_next (node)) {
3276 GtkTextTag *tag = (GtkTextTag *) node->data;
3277 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3278 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3279 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3281 offset = gtk_text_iter_get_offset (&match_start);
3282 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3283 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3287 gtk_text_iter_forward_char (&iter);
3292 message_is_empty (ModestMsgEditWindow *window)
3294 ModestMsgEditWindowPrivate *priv = NULL;
3296 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3297 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3299 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3300 * so we can ignore markup.
3302 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3305 count = gtk_text_buffer_get_char_count (buf);
3311 msg_body_focus (GtkWidget *focus,
3312 GdkEventFocus *event,
3316 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3317 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3318 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3323 recpt_field_changed (GtkTextBuffer *buffer,
3324 ModestMsgEditWindow *editor)
3326 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3327 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3331 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3333 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3334 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3338 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3341 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3342 GtkTextBuffer *buffer;
3344 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3345 gtk_text_buffer_set_modified (buffer, modified);
3346 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3347 gtk_text_buffer_set_modified (buffer, modified);
3348 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3349 gtk_text_buffer_set_modified (buffer, modified);
3350 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3354 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3356 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3357 const char *account_name;
3358 GtkTextBuffer *buffer;
3360 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3361 if (gtk_text_buffer_get_modified (buffer))
3363 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3364 if (gtk_text_buffer_get_modified (buffer))
3366 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3367 if (gtk_text_buffer_get_modified (buffer))
3369 if (gtk_text_buffer_get_modified (priv->text_buffer))
3372 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3373 if (priv->original_mailbox) {
3374 if (!account_name || strcmp (account_name, priv->original_mailbox))
3376 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3387 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3389 ModestMsgEditWindowPrivate *priv = NULL;
3390 GSList *address_list = NULL;
3392 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3393 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3395 /* check if there's no recipient added */
3396 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3397 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3398 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3399 /* no recipient contents, then select contacts */
3400 modest_msg_edit_window_open_addressbook (window, NULL);
3405 g_object_ref (window);
3406 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field),
3407 (add_to_addressbook) ? &address_list : NULL)) {
3408 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3409 g_object_unref (window);
3412 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field),
3413 (add_to_addressbook) ? &address_list : NULL)) {
3414 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3415 g_object_unref (window);
3418 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field),
3419 (add_to_addressbook) ? &address_list : NULL)) {
3420 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3421 g_object_unref (window);
3425 /* Add contacts to address book */
3426 if (add_to_addressbook && address_list)
3427 modest_address_book_add_address_list (address_list);
3429 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3430 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3431 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3432 g_object_unref (window);
3439 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3440 ModestMsgEditWindow *window)
3442 modest_msg_edit_window_offer_attach_file (window);
3446 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3448 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3450 return priv->clipboard_text;
3454 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3456 ModestMsgEditWindow *window)
3458 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3459 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3462 /* It could happen that the window was already closed */
3463 if (!GTK_WIDGET_VISIBLE (window))
3466 g_object_ref (window);
3467 text = gtk_clipboard_wait_for_text (selection_clipboard);
3469 if (priv->clipboard_text != NULL) {
3470 g_free (priv->clipboard_text);
3472 priv->clipboard_text = text;
3474 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3476 g_object_unref (window);
3479 static gboolean clipboard_owner_change_idle (gpointer userdata)
3481 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3482 ModestMsgEditWindowPrivate *priv;
3484 gdk_threads_enter ();
3485 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3488 priv->clipboard_owner_idle = 0;
3489 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3490 gdk_threads_leave ();
3496 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3498 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3499 if (priv->clipboard_owner_idle == 0) {
3500 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3501 clipboard_owner_change_idle,
3502 g_object_ref (window),
3508 subject_field_move_cursor (GtkEntry *entry,
3509 GtkMovementStep step,
3514 /* It could happen that the window was already closed */
3515 if (!GTK_WIDGET_VISIBLE (window))
3518 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3522 update_window_title (ModestMsgEditWindow *window)
3524 ModestMsgEditWindowPrivate *priv = NULL;
3525 const gchar *subject;
3527 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3528 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3529 if (subject == NULL || subject[0] == '\0')
3530 subject = _("mail_va_new_email");
3532 gtk_window_set_title (GTK_WINDOW (window), subject);
3538 body_insert_text (GtkTextBuffer *buffer,
3539 GtkTextIter *location,
3542 ModestMsgEditWindow *window)
3544 GtkTextIter end_iter;
3551 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3553 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3555 offset = gtk_text_iter_get_offset (&end_iter);
3556 line = gtk_text_iter_get_line (&end_iter);
3560 while (text_offset < text + len) {
3561 if (*text_offset == '\n')
3563 if (text_lines + line >= MAX_BODY_LINES) {
3564 len = text_offset - text;
3570 utf8_len = g_utf8_strlen (text, len);
3572 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3573 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3574 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3579 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3581 /* Prevent endless recursion */
3582 result = g_strndup (text, utf8_end - text);
3583 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3584 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3585 (gpointer) result, (gpointer) (utf8_end - text),
3587 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3591 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3592 if (priv->max_chars_banner == NULL) {
3593 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3594 _CS("ckdg_ib_maximum_characters_reached"));
3595 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3601 subject_field_changed (GtkEditable *editable,
3602 ModestMsgEditWindow *window)
3604 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3605 update_window_title (window);
3606 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3607 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3608 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3611 subject_field_insert_text (GtkEditable *editable,
3613 gint new_text_length,
3615 ModestMsgEditWindow *window)
3617 GString *result = g_string_new ("");
3619 gint result_len = 0;
3620 const gchar *entry_text = NULL;
3623 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3624 old_length = g_utf8_strlen (entry_text, -1);
3626 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3627 gunichar c = g_utf8_get_char_validated (current, 8);
3628 /* Invalid unichar, stop */
3634 result = g_string_append_unichar (result, c);
3638 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3639 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3642 /* Prevent endless recursion */
3643 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3644 g_signal_emit_by_name (editable, "insert-text",
3645 (gpointer) result->str, (gpointer) result->len,
3646 (gpointer) position, (gpointer) window);
3647 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3651 if (result_len + old_length > 1000) {
3652 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3653 _CS("ckdg_ib_maximum_characters_reached"));
3655 g_string_free (result, TRUE);
3659 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3662 ModestMsgEditWindowPrivate *priv = NULL;
3664 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3665 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3667 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3670 gtk_widget_show_all (priv->find_toolbar);
3671 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3673 gtk_widget_hide_all (priv->find_toolbar);
3674 gtk_widget_grab_focus (priv->msg_body);
3679 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3681 GtkTextIter *match_start,
3682 GtkTextIter *match_end)
3684 GtkTextIter end_iter;
3685 gchar *str_casefold;
3688 gchar *range_casefold;
3691 gboolean result = FALSE;
3698 gtk_text_iter_forward_to_end (&end_iter);
3700 str_casefold = g_utf8_casefold (str, -1);
3701 str_chars_n = strlen (str);
3703 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3704 range_casefold = g_utf8_casefold (range_text, -1);
3705 range_chars_n = strlen (range_casefold);
3707 if (range_chars_n < str_chars_n) {
3708 g_free (str_casefold);
3709 g_free (range_text);
3710 g_free (range_casefold);
3714 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3715 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3716 if (!g_utf8_collate (range_subtext, str_casefold)) {
3717 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3719 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3720 match_start, match_end, NULL)) {
3721 g_debug ("Matched string with collate, but not matched in model");
3723 g_free (found_text);
3725 g_free (range_subtext);
3729 g_free (str_casefold);
3730 g_free (range_text);
3731 g_free (range_casefold);
3738 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3739 ModestMsgEditWindow *window)
3741 gchar *current_search = NULL;
3742 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3744 GtkTextIter selection_start, selection_end;
3745 GtkTextIter match_start, match_end;
3746 gboolean continue_search = FALSE;
3748 if (message_is_empty (window)) {
3749 g_free (priv->last_search);
3750 priv->last_search = NULL;
3751 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3755 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3756 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3757 g_free (current_search);
3758 g_free (priv->last_search);
3759 priv->last_search = NULL;
3760 /* Information banner about empty search */
3761 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3765 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3766 continue_search = TRUE;
3768 g_free (priv->last_search);
3769 priv->last_search = g_strdup (current_search);
3772 if (continue_search) {
3773 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3774 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3775 &match_start, &match_end);
3777 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3779 GtkTextIter buffer_start;
3780 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3781 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3782 &match_start, &match_end);
3784 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3787 /* Mark as selected the string found in search */
3789 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3790 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3791 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3793 g_free (priv->last_search);
3794 priv->last_search = NULL;
3796 g_free (current_search);
3800 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3802 ModestMsgEditWindowPrivate *priv;
3804 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3809 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3812 ModestMsgEditWindowPrivate *priv;
3814 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3819 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3820 ModestMsgEditWindow *window)
3822 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3826 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3829 ModestMsgEditWindowPrivate *priv;
3830 TnyHeader *header = NULL;
3832 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3833 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3835 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3837 if (priv->draft_msg != NULL) {
3838 g_object_unref (priv->draft_msg);
3841 if (draft != NULL) {
3842 g_object_ref (draft);
3843 header = tny_msg_get_header (draft);
3844 if (priv->msg_uid) {
3845 g_free (priv->msg_uid);
3846 priv->msg_uid = NULL;
3848 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3851 priv->draft_msg = draft;
3855 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3856 GtkTextIter *start, GtkTextIter *end,
3859 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3860 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3863 if (tag == NULL) return;
3864 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3865 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3866 replace_with_images (window, priv->images);
3871 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3874 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3876 g_return_if_fail (TNY_IS_MIME_PART (part));
3877 tny_list_prepend (priv->attachments, (GObject *) part);
3878 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3879 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3880 gtk_widget_show_all (priv->attachments_caption);
3881 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3885 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3887 ModestMsgEditWindowPrivate *priv;
3889 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3890 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3892 return priv->msg_uid;
3896 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3897 ModestMsgEditWindowWidgetType widget_type)
3899 ModestMsgEditWindowPrivate *priv;
3901 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3904 switch (widget_type) {
3905 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3906 return priv->msg_body;
3908 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3909 return priv->to_field;
3911 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3912 return priv->cc_field;
3914 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3915 return priv->bcc_field;
3917 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3918 return priv->subject_field;
3920 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3921 return priv->attachments_view;
3929 remove_tags (WPTextBuffer *buffer)
3931 GtkTextIter start, end;
3933 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3934 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3936 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3940 on_account_removed (TnyAccountStore *account_store,
3941 TnyAccount *account,
3944 /* Do nothing if it's a store account, because we use the
3945 transport to send the messages */
3946 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3947 const gchar *parent_acc = NULL;
3948 const gchar *our_acc = NULL;
3950 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3951 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3952 /* Close this window if I'm showing a message of the removed account */
3953 if (strcmp (parent_acc, our_acc) == 0)
3954 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3959 update_signature (ModestMsgEditWindow *self,
3960 const gchar *old_account,
3961 const gchar *new_account)
3963 ModestMsgEditWindowPrivate *priv;
3964 gboolean has_old_signature, has_new_signature;
3966 ModestAccountMgr *mgr;
3969 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3971 gtk_text_buffer_begin_user_action (priv->text_buffer);
3973 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3974 mgr = modest_runtime_get_account_mgr ();
3978 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3979 if (has_old_signature) {
3980 GtkTextIter match_start, match_end;
3982 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
3983 seems that the search has some problems
3984 with the blank space at the end */
3985 if (gtk_text_iter_forward_search (&iter, "--",
3986 GTK_TEXT_SEARCH_TEXT_ONLY,
3987 &match_start, NULL, NULL)) {
3988 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
3989 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3991 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3992 &match_start, &match_end, NULL)) {
3996 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
4001 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4002 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4003 if (has_new_signature) {
4005 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4006 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4008 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4009 g_free (full_signature);
4012 gtk_text_buffer_end_user_action (priv->text_buffer);
4015 static void update_branding (ModestMsgEditWindow *self,
4016 const gchar *new_account)
4018 ModestMsgEditWindowPrivate *priv;
4019 ModestAccountMgr *mgr;
4020 const GdkPixbuf *new_icon = NULL;
4021 gchar *new_label = NULL;
4022 gboolean show = FALSE;
4024 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4026 mgr = modest_runtime_get_account_mgr ();
4028 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4030 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4031 gtk_widget_show (priv->brand_icon);
4034 gtk_widget_hide (priv->brand_icon);
4037 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4038 gtk_widget_show (priv->brand_label);
4042 gtk_widget_hide (priv->brand_label);
4046 gtk_widget_show (priv->brand_container);
4048 gtk_widget_hide (priv->brand_container);
4052 from_field_changed (HildonPickerButton *button,
4053 ModestMsgEditWindow *self)
4055 ModestMsgEditWindowPrivate *priv;
4056 gchar *old_account, *new_account;
4058 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4060 old_account = priv->last_from_account;
4061 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4064 g_warning ("%s, could not get the new account", __FUNCTION__);
4068 /* If the From is the same do nothing */
4069 if (old_account && new_account && !strcmp (old_account, new_account))
4072 priv->last_from_account = new_account;
4074 update_signature (self, old_account, new_account);
4075 update_branding (self, new_account);
4079 typedef struct _MessageSettingsHelper {
4080 ModestMsgEditWindow *window;
4081 GSList *priority_group;
4082 GSList *format_group;
4083 GtkToggleButton *current_priority;
4084 GtkToggleButton *current_format;
4085 } MessageSettingsHelper;
4088 on_priority_toggle (GtkToggleButton *button,
4089 MessageSettingsHelper *helper)
4092 ModestMsgEditWindowPrivate *priv;
4094 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4095 if (gtk_toggle_button_get_active (button)) {
4097 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4098 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4099 if ((node_button != button) &&
4100 gtk_toggle_button_get_active (node_button)) {
4101 gtk_toggle_button_set_active (node_button, FALSE);
4104 helper->current_priority = button;
4106 gboolean found = FALSE;
4107 /* If no one is active, activate it again */
4108 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4109 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4110 if (gtk_toggle_button_get_active (node_button)) {
4116 gtk_toggle_button_set_active (button, TRUE);
4122 on_format_toggle (GtkToggleButton *button,
4123 MessageSettingsHelper *helper)
4126 ModestMsgEditWindowPrivate *priv;
4128 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4129 if (gtk_toggle_button_get_active (button)) {
4131 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4132 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4133 if ((node_button != button) &&
4134 gtk_toggle_button_get_active (node_button)) {
4135 gtk_toggle_button_set_active (node_button, FALSE);
4138 helper->current_format = button;
4140 gboolean found = FALSE;
4141 /* If no one is active, activate it again */
4142 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4143 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4144 if (gtk_toggle_button_get_active (node_button)) {
4150 gtk_toggle_button_set_active (button, TRUE);
4157 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4162 GtkWidget *priority_hbox;
4163 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4164 GtkWidget *captioned;
4165 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4166 GtkWidget *format_hbox;
4167 GtkWidget *html_toggle, *text_toggle;
4168 ModestMsgEditWindowPrivate *priv;
4169 MessageSettingsHelper helper = {0,};
4171 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4172 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4173 helper.window = window;
4174 helper.priority_group = NULL;
4175 helper.format_group = NULL;
4177 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4178 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4180 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4181 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4182 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4183 vbox = gtk_vbox_new (FALSE, 0);
4184 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4185 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4186 gtk_container_add (GTK_CONTAINER (align), vbox);
4187 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4188 gtk_widget_show (align);
4189 gtk_widget_show (vbox);
4191 /* Priority toggles */
4192 priority_hbox = gtk_hbox_new (TRUE, 0);
4193 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4194 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4195 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4196 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4197 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4198 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4199 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4200 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4201 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4202 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4203 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4204 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4205 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4206 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4207 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4208 gtk_widget_show_all (priority_hbox);
4209 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4210 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4211 gtk_widget_show (captioned);
4212 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4214 /* format toggles */
4215 format_hbox = gtk_hbox_new (TRUE, 0);
4216 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4217 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4218 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4219 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4220 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4221 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4222 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4223 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4224 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4225 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4226 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4227 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4228 gtk_widget_show_all (format_hbox);
4229 gtk_widget_show (format_hbox);
4230 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4233 g_object_unref (title_sizegroup);
4234 g_object_unref (value_sizegroup);
4236 /* Set current values */
4237 switch (priv->priority_flags) {
4238 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4239 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4240 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4242 case TNY_HEADER_FLAG_LOW_PRIORITY:
4243 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4244 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4247 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4248 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4252 switch (modest_msg_edit_window_get_format (window)) {
4253 case MODEST_MSG_EDIT_FORMAT_TEXT:
4254 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4255 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4257 case MODEST_MSG_EDIT_FORMAT_HTML:
4259 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4260 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4264 /* Signal connects */
4265 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4266 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4267 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4268 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4269 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4271 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4272 GTK_WINDOW (dialog), GTK_WINDOW (window));
4274 /* Save settings if the user clicked on done */
4275 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4276 TnyHeaderFlags flags;
4277 ModestMsgEditFormat old_format, new_format;
4279 /* Set priority flags */
4280 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4281 if (priv->priority_flags != flags)
4282 modest_msg_edit_window_set_priority_flags (window, flags);
4284 /* Set edit format */
4285 old_format = modest_msg_edit_window_get_format (window);
4286 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4287 if (old_format != new_format) {
4288 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4289 modest_msg_edit_window_set_file_format (window, file_format);
4293 gtk_widget_destroy (dialog);
4294 g_slist_free (helper.priority_group);
4298 on_message_settings (GtkAction *action,
4299 ModestMsgEditWindow *window)
4301 modest_msg_edit_window_show_msg_settings_dialog (window);
4305 on_cc_button_toggled (HildonCheckButton *button,
4306 ModestMsgEditWindow *window)
4308 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4310 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4311 hildon_check_button_get_active (button));
4315 on_bcc_button_toggled (HildonCheckButton *button,
4316 ModestMsgEditWindow *window)
4318 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4320 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4321 hildon_check_button_get_active (button));
4325 setup_menu (ModestMsgEditWindow *self)
4327 ModestMsgEditWindowPrivate *priv = NULL;
4329 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4333 /* Settings menu buttons */
4334 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4335 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4337 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4338 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4339 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4341 priv->cc_button = hildon_check_button_new (0);
4342 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4343 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4345 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4347 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4348 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4349 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4350 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4352 priv->bcc_button = hildon_check_button_new (0);
4353 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4354 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4356 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4358 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4359 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4360 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4361 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4363 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4364 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4365 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4366 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4367 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4369 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4370 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4371 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4372 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4373 APP_MENU_CALLBACK (on_message_settings),
4375 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4376 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4381 emit_open_addressbook (GtkButton *button,
4382 ModestRecptEditor *editor)
4384 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4388 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4389 const gchar *label, GtkWidget *control)
4391 GtkWidget *abook_button;
4394 GtkWidget *label_widget;
4396 box = gtk_hbox_new (FALSE, 0);
4398 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4399 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4401 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4402 label_widget = gtk_label_new (label);
4403 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4404 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4406 gtk_container_add (GTK_CONTAINER (align), abook_button);
4407 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4408 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4409 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4410 if (title_size_group)
4411 gtk_size_group_add_widget (title_size_group, label_widget);
4412 if (value_size_group)
4413 gtk_size_group_add_widget (value_size_group, control);
4415 g_signal_connect (G_OBJECT (abook_button), "clicked",
4416 G_CALLBACK (emit_open_addressbook), control);
4422 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4424 ModestMsgEditWindowPrivate *priv = NULL;
4426 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4428 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4429 priv->max_chars_banner = NULL;