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;
2715 GdkColor *new_color;
2716 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2718 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), new_color);
2720 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2722 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2726 font_size_clicked (GtkToolButton *button,
2727 ModestMsgEditWindow *window)
2729 ModestMsgEditWindowPrivate *priv;
2730 GtkWidget *selector, *dialog;
2732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2734 selector = hildon_touch_selector_new ();
2735 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2736 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2738 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2739 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2740 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2742 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2746 WPTextBufferFormat format;
2748 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2750 memset (&format, 0, sizeof (format));
2751 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2753 format.cs.font_size = TRUE;
2754 format.cs.text_position = TRUE;
2755 format.cs.font = TRUE;
2756 format.font_size = new_index;
2757 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2759 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2760 GINT_TO_POINTER (new_index)))
2761 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2763 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2764 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2765 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2766 size_text, "</span>", NULL);
2768 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2772 gtk_widget_destroy (dialog);
2774 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2779 font_face_clicked (GtkToolButton *button,
2780 ModestMsgEditWindow *window)
2782 ModestMsgEditWindowPrivate *priv;
2783 GtkWidget *selector, *dialog;
2784 GtkCellRenderer *renderer;
2786 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2788 selector = hildon_touch_selector_new ();
2789 renderer = gtk_cell_renderer_text_new ();
2790 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2791 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2792 renderer, "family", 0, "text", 0, NULL);
2793 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2795 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2796 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2797 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2799 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2800 gint new_font_index;
2804 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2805 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2806 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2810 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2812 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2813 GINT_TO_POINTER(new_font_index)))
2814 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2816 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2817 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2819 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2823 gtk_tree_path_free (path);
2826 gtk_widget_destroy (dialog);
2828 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2833 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2836 ModestMsgEditWindowPrivate *priv = NULL;
2837 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2839 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2840 if (!priv->update_caption_visibility)
2843 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2845 gtk_widget_show (priv->cc_caption);
2847 gtk_widget_hide (priv->cc_caption);
2849 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2853 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2856 ModestMsgEditWindowPrivate *priv = NULL;
2857 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2859 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2860 if (!priv->update_caption_visibility)
2863 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2865 gtk_widget_show (priv->bcc_caption);
2867 gtk_widget_hide (priv->bcc_caption);
2869 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2873 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2874 ModestRecptEditor *editor)
2876 ModestMsgEditWindowPrivate *priv;
2878 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2879 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2881 /* we check for low-mem; in that case, show a warning, and don't allow
2882 * for the addressbook
2884 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2889 if (editor == NULL) {
2890 GtkWidget *view_focus, *parent;
2891 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2893 /* This code should be kept in sync with ModestRecptEditor. The
2894 textview inside the recpt editor is the one that really gets the
2895 focus. As it's inside a scrolled window, and this one inside the
2896 hbox recpt editor inherits from, we'll need to go up in the
2897 hierarchy to know if the text view is part of the recpt editor
2898 or if it's a different text entry */
2899 parent = gtk_widget_get_parent (view_focus);
2900 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2901 editor = MODEST_RECPT_EDITOR (parent);
2904 editor = MODEST_RECPT_EDITOR (priv->to_field);
2907 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2911 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2913 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2915 modest_msg_edit_window_open_addressbook (window, NULL);
2919 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2920 gboolean show_toolbar)
2922 ModestWindowPrivate *parent_priv;
2923 ModestMsgEditWindowPrivate *priv;
2925 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2927 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2929 /* We can not just use the code of
2930 modest_msg_edit_window_setup_toolbar because it has a
2931 mixture of both initialization and creation code. */
2933 gint current_format;
2934 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2935 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2936 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
2937 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2939 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2942 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2947 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2948 TnyHeaderFlags priority_flags)
2950 ModestMsgEditWindowPrivate *priv;
2951 ModestWindowPrivate *parent_priv;
2953 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2955 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2956 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2958 if (priv->priority_flags != priority_flags) {
2959 GtkAction *priority_action = NULL;
2961 priv->priority_flags = priority_flags;
2963 switch (priority_flags) {
2964 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2965 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2966 MODEST_HEADER_ICON_HIGH,
2967 HILDON_ICON_SIZE_SMALL);
2968 gtk_widget_show (priv->priority_icon);
2969 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2970 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2972 case TNY_HEADER_FLAG_LOW_PRIORITY:
2973 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
2974 MODEST_HEADER_ICON_LOW,
2975 HILDON_ICON_SIZE_SMALL);
2976 gtk_widget_show (priv->priority_icon);
2977 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2978 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2981 gtk_widget_hide (priv->priority_icon);
2982 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2983 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2986 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2987 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2989 gtk_widget_queue_resize (priv->subject_box);
2993 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2996 ModestMsgEditWindowPrivate *priv;
2997 ModestWindowPrivate *parent_priv;
2998 gint current_format;
3000 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3002 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3003 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3005 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3006 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3008 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3010 if (current_format != file_format) {
3011 switch (file_format) {
3012 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3013 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3014 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3015 if (parent_priv->toolbar)
3016 gtk_widget_show (parent_priv->toolbar);
3018 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3022 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3023 response = gtk_dialog_run (GTK_DIALOG (dialog));
3024 gtk_widget_destroy (dialog);
3025 if (response == GTK_RESPONSE_OK) {
3026 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3027 if (parent_priv->toolbar)
3028 gtk_widget_hide (parent_priv->toolbar);
3030 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3031 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3036 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3037 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3038 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3043 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3046 ModestMsgEditWindowPrivate *priv;
3047 WPTextBufferFormat oldfmt, fmt;
3048 gint old_position = 0;
3052 GdkColor *color = NULL;
3053 gboolean bold, bold_set, italic, italic_set;
3054 gboolean underline, underline_set;
3055 gboolean strikethrough, strikethrough_set;
3056 gboolean position_set;
3057 gboolean font_size_set, font_set, color_set;
3060 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3061 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3063 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3064 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3065 GTK_WINDOW(dialog), GTK_WINDOW (window));
3067 /* First we get the currently selected font information */
3068 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3070 switch (oldfmt.text_position) {
3071 case TEXT_POSITION_NORMAL:
3074 case TEXT_POSITION_SUPERSCRIPT:
3082 g_object_set (G_OBJECT (dialog),
3083 "bold", oldfmt.bold != FALSE,
3084 "bold-set", !oldfmt.cs.bold,
3085 "underline", oldfmt.underline != FALSE,
3086 "underline-set", !oldfmt.cs.underline,
3087 "italic", oldfmt.italic != FALSE,
3088 "italic-set", !oldfmt.cs.italic,
3089 "strikethrough", oldfmt.strikethrough != FALSE,
3090 "strikethrough-set", !oldfmt.cs.strikethrough,
3091 "color", &oldfmt.color,
3092 "color-set", !oldfmt.cs.color,
3093 "size", wp_font_size[oldfmt.font_size],
3094 "size-set", !oldfmt.cs.font_size,
3095 "position", old_position,
3096 "position-set", !oldfmt.cs.text_position,
3097 "family", wp_get_font_name (oldfmt.font),
3098 "family-set", !oldfmt.cs.font,
3101 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3102 GTK_WINDOW (dialog), GTK_WINDOW (window));
3103 gtk_widget_show_all (dialog);
3104 priv->font_dialog = dialog;
3105 response = gtk_dialog_run (GTK_DIALOG (dialog));
3106 priv->font_dialog = NULL;
3107 if (response == GTK_RESPONSE_OK) {
3109 g_object_get( dialog,
3111 "bold-set", &bold_set,
3112 "underline", &underline,
3113 "underline-set", &underline_set,
3115 "italic-set", &italic_set,
3116 "strikethrough", &strikethrough,
3117 "strikethrough-set", &strikethrough_set,
3119 "color-set", &color_set,
3121 "size-set", &font_size_set,
3122 "family", &font_name,
3123 "family-set", &font_set,
3124 "position", &position,
3125 "position-set", &position_set,
3130 if (response == GTK_RESPONSE_OK) {
3131 memset(&fmt, 0, sizeof(fmt));
3137 fmt.italic = italic;
3138 fmt.cs.italic = TRUE;
3140 if (underline_set) {
3141 fmt.underline = underline;
3142 fmt.cs.underline = TRUE;
3144 if (strikethrough_set) {
3145 fmt.strikethrough = strikethrough;
3146 fmt.cs.strikethrough = TRUE;
3151 ? TEXT_POSITION_NORMAL
3152 : ( ( position == 1 )
3153 ? TEXT_POSITION_SUPERSCRIPT
3154 : TEXT_POSITION_SUBSCRIPT );
3155 fmt.cs.text_position = TRUE;
3156 fmt.font_size = oldfmt.font_size;
3160 fmt.cs.color = TRUE;
3163 fmt.font = wp_get_font_index(font_name,
3168 if (font_size_set) {
3169 fmt.cs.font_size = TRUE;
3170 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3172 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3173 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3175 gtk_widget_destroy (dialog);
3177 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3181 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3183 ModestMsgEditWindowPrivate *priv;
3184 ModestWindowPrivate *parent_priv;
3185 gboolean was_rich_text, is_rich_text;
3187 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3188 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3189 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3191 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3193 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3195 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3197 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3199 gtk_widget_show (parent_priv->toolbar);
3201 gtk_widget_hide (parent_priv->toolbar);
3204 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3205 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3209 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3211 ModestMsgEditWindowPrivate *priv;
3213 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3214 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3216 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3218 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3219 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3224 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3226 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3228 priv->can_undo = can_undo;
3232 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3234 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3236 priv->can_redo = can_redo;
3240 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3242 ModestMsgEditWindowPrivate *priv;
3243 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3244 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3246 return priv->can_undo;
3250 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3252 ModestMsgEditWindowPrivate *priv;
3253 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3254 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 return priv->can_redo;
3261 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3264 GtkTextIter match_start, match_end;
3266 if (image_id == NULL)
3269 gtk_text_buffer_get_start_iter (buffer, &iter);
3271 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3272 GSList *tags = gtk_text_iter_get_tags (&match_start);
3274 for (node = tags; node != NULL; node = g_slist_next (node)) {
3275 GtkTextTag *tag = (GtkTextTag *) node->data;
3276 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3277 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3278 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3280 offset = gtk_text_iter_get_offset (&match_start);
3281 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3282 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3286 gtk_text_iter_forward_char (&iter);
3291 message_is_empty (ModestMsgEditWindow *window)
3293 ModestMsgEditWindowPrivate *priv = NULL;
3295 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3296 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3298 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3299 * so we can ignore markup.
3301 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3304 count = gtk_text_buffer_get_char_count (buf);
3310 msg_body_focus (GtkWidget *focus,
3311 GdkEventFocus *event,
3315 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3316 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3317 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3322 recpt_field_changed (GtkTextBuffer *buffer,
3323 ModestMsgEditWindow *editor)
3325 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3326 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3330 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3332 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3333 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3337 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3340 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3341 GtkTextBuffer *buffer;
3343 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3344 gtk_text_buffer_set_modified (buffer, modified);
3345 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3346 gtk_text_buffer_set_modified (buffer, modified);
3347 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3348 gtk_text_buffer_set_modified (buffer, modified);
3349 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3353 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3355 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3356 const char *account_name;
3357 GtkTextBuffer *buffer;
3359 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3360 if (gtk_text_buffer_get_modified (buffer))
3362 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3363 if (gtk_text_buffer_get_modified (buffer))
3365 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3366 if (gtk_text_buffer_get_modified (buffer))
3368 if (gtk_text_buffer_get_modified (priv->text_buffer))
3371 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3372 if (priv->original_mailbox) {
3373 if (!account_name || strcmp (account_name, priv->original_mailbox))
3375 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3386 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3388 ModestMsgEditWindowPrivate *priv = NULL;
3389 GSList *address_list = NULL;
3391 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3392 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3394 /* check if there's no recipient added */
3395 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3396 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3397 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3398 /* no recipient contents, then select contacts */
3399 modest_msg_edit_window_open_addressbook (window, NULL);
3404 g_object_ref (window);
3405 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3406 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3407 g_object_unref (window);
3410 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3411 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3412 g_object_unref (window);
3415 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3416 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3417 g_object_unref (window);
3421 /* Add contacts to address book */
3423 modest_address_book_add_address_list (address_list);
3425 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3426 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3427 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3428 g_object_unref (window);
3435 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3436 ModestMsgEditWindow *window)
3438 modest_msg_edit_window_offer_attach_file (window);
3442 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3444 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3446 return priv->clipboard_text;
3450 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3452 ModestMsgEditWindow *window)
3454 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3455 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3458 /* It could happen that the window was already closed */
3459 if (!GTK_WIDGET_VISIBLE (window))
3462 g_object_ref (window);
3463 text = gtk_clipboard_wait_for_text (selection_clipboard);
3465 if (priv->clipboard_text != NULL) {
3466 g_free (priv->clipboard_text);
3468 priv->clipboard_text = text;
3470 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3472 g_object_unref (window);
3475 static gboolean clipboard_owner_change_idle (gpointer userdata)
3477 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3478 ModestMsgEditWindowPrivate *priv;
3480 gdk_threads_enter ();
3481 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3482 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3484 priv->clipboard_owner_idle = 0;
3485 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3486 gdk_threads_leave ();
3492 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3494 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3495 if (priv->clipboard_owner_idle == 0) {
3496 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3497 clipboard_owner_change_idle,
3498 g_object_ref (window),
3504 subject_field_move_cursor (GtkEntry *entry,
3505 GtkMovementStep step,
3510 /* It could happen that the window was already closed */
3511 if (!GTK_WIDGET_VISIBLE (window))
3514 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3518 update_window_title (ModestMsgEditWindow *window)
3520 ModestMsgEditWindowPrivate *priv = NULL;
3521 const gchar *subject;
3523 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3524 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3525 if (subject == NULL || subject[0] == '\0')
3526 subject = _("mail_va_new_email");
3528 gtk_window_set_title (GTK_WINDOW (window), subject);
3534 body_insert_text (GtkTextBuffer *buffer,
3535 GtkTextIter *location,
3538 ModestMsgEditWindow *window)
3540 GtkTextIter end_iter;
3547 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3549 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3551 offset = gtk_text_iter_get_offset (&end_iter);
3552 line = gtk_text_iter_get_line (&end_iter);
3556 while (text_offset < text + len) {
3557 if (*text_offset == '\n')
3559 if (text_lines + line >= MAX_BODY_LINES) {
3560 len = text_offset - text;
3566 utf8_len = g_utf8_strlen (text, len);
3568 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3569 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3570 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3575 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3577 /* Prevent endless recursion */
3578 result = g_strndup (text, utf8_end - text);
3579 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3580 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3581 (gpointer) result, (gpointer) (utf8_end - text),
3583 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3587 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3588 if (priv->max_chars_banner == NULL) {
3589 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3590 _CS("ckdg_ib_maximum_characters_reached"));
3591 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3597 subject_field_changed (GtkEditable *editable,
3598 ModestMsgEditWindow *window)
3600 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3601 update_window_title (window);
3602 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3603 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3604 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3607 subject_field_insert_text (GtkEditable *editable,
3609 gint new_text_length,
3611 ModestMsgEditWindow *window)
3613 GString *result = g_string_new ("");
3615 gint result_len = 0;
3616 const gchar *entry_text = NULL;
3619 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3620 old_length = g_utf8_strlen (entry_text, -1);
3622 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3623 gunichar c = g_utf8_get_char_validated (current, 8);
3624 /* Invalid unichar, stop */
3630 result = g_string_append_unichar (result, c);
3634 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3635 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3638 /* Prevent endless recursion */
3639 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3640 g_signal_emit_by_name (editable, "insert-text",
3641 (gpointer) result->str, (gpointer) result->len,
3642 (gpointer) position, (gpointer) window);
3643 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3647 if (result_len + old_length > 1000) {
3648 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3649 _CS("ckdg_ib_maximum_characters_reached"));
3651 g_string_free (result, TRUE);
3655 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3658 ModestMsgEditWindowPrivate *priv = NULL;
3660 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3661 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3663 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3666 gtk_widget_show_all (priv->find_toolbar);
3667 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3669 gtk_widget_hide_all (priv->find_toolbar);
3670 gtk_widget_grab_focus (priv->msg_body);
3675 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3677 GtkTextIter *match_start,
3678 GtkTextIter *match_end)
3680 GtkTextIter end_iter;
3681 gchar *str_casefold;
3684 gchar *range_casefold;
3687 gboolean result = FALSE;
3694 gtk_text_iter_forward_to_end (&end_iter);
3696 str_casefold = g_utf8_casefold (str, -1);
3697 str_chars_n = strlen (str);
3699 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3700 range_casefold = g_utf8_casefold (range_text, -1);
3701 range_chars_n = strlen (range_casefold);
3703 if (range_chars_n < str_chars_n) {
3704 g_free (str_casefold);
3705 g_free (range_text);
3706 g_free (range_casefold);
3710 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3711 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3712 if (!g_utf8_collate (range_subtext, str_casefold)) {
3713 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3715 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3716 match_start, match_end, NULL)) {
3717 g_debug ("Matched string with collate, but not matched in model");
3719 g_free (found_text);
3721 g_free (range_subtext);
3725 g_free (str_casefold);
3726 g_free (range_text);
3727 g_free (range_casefold);
3734 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3735 ModestMsgEditWindow *window)
3737 gchar *current_search = NULL;
3738 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3740 GtkTextIter selection_start, selection_end;
3741 GtkTextIter match_start, match_end;
3742 gboolean continue_search = FALSE;
3744 if (message_is_empty (window)) {
3745 g_free (priv->last_search);
3746 priv->last_search = NULL;
3747 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3751 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3752 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3753 g_free (current_search);
3754 g_free (priv->last_search);
3755 priv->last_search = NULL;
3756 /* Information banner about empty search */
3757 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3761 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3762 continue_search = TRUE;
3764 g_free (priv->last_search);
3765 priv->last_search = g_strdup (current_search);
3768 if (continue_search) {
3769 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3770 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3771 &match_start, &match_end);
3773 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3775 GtkTextIter buffer_start;
3776 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3777 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3778 &match_start, &match_end);
3780 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3783 /* Mark as selected the string found in search */
3785 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3786 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3787 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3789 g_free (priv->last_search);
3790 priv->last_search = NULL;
3792 g_free (current_search);
3796 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3798 ModestMsgEditWindowPrivate *priv;
3800 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3805 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3808 ModestMsgEditWindowPrivate *priv;
3810 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3815 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3816 ModestMsgEditWindow *window)
3818 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3822 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3825 ModestMsgEditWindowPrivate *priv;
3826 TnyHeader *header = NULL;
3828 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3829 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3831 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3833 if (priv->draft_msg != NULL) {
3834 g_object_unref (priv->draft_msg);
3837 if (draft != NULL) {
3838 g_object_ref (draft);
3839 header = tny_msg_get_header (draft);
3840 if (priv->msg_uid) {
3841 g_free (priv->msg_uid);
3842 priv->msg_uid = NULL;
3844 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3847 priv->draft_msg = draft;
3851 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3852 GtkTextIter *start, GtkTextIter *end,
3855 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3856 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3859 if (tag == NULL) return;
3860 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3861 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3862 replace_with_images (window, priv->images);
3867 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3870 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3872 g_return_if_fail (TNY_IS_MIME_PART (part));
3873 tny_list_prepend (priv->attachments, (GObject *) part);
3874 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3875 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3876 gtk_widget_show_all (priv->attachments_caption);
3877 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3881 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3883 ModestMsgEditWindowPrivate *priv;
3885 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3886 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3888 return priv->msg_uid;
3892 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3893 ModestMsgEditWindowWidgetType widget_type)
3895 ModestMsgEditWindowPrivate *priv;
3897 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3898 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3900 switch (widget_type) {
3901 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3902 return priv->msg_body;
3904 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3905 return priv->to_field;
3907 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3908 return priv->cc_field;
3910 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3911 return priv->bcc_field;
3913 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3914 return priv->subject_field;
3916 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3917 return priv->attachments_view;
3925 remove_tags (WPTextBuffer *buffer)
3927 GtkTextIter start, end;
3929 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3930 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3932 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3936 on_account_removed (TnyAccountStore *account_store,
3937 TnyAccount *account,
3940 /* Do nothing if it's a store account, because we use the
3941 transport to send the messages */
3942 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3943 const gchar *parent_acc = NULL;
3944 const gchar *our_acc = NULL;
3946 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3947 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3948 /* Close this window if I'm showing a message of the removed account */
3949 if (strcmp (parent_acc, our_acc) == 0)
3950 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3955 update_signature (ModestMsgEditWindow *self,
3956 const gchar *old_account,
3957 const gchar *new_account)
3959 ModestMsgEditWindowPrivate *priv;
3960 gboolean has_old_signature, has_new_signature;
3962 ModestAccountMgr *mgr;
3965 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
3967 gtk_text_buffer_begin_user_action (priv->text_buffer);
3969 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
3970 mgr = modest_runtime_get_account_mgr ();
3974 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
3975 if (has_old_signature) {
3976 GtkTextIter match_start, match_end;
3978 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
3979 seems that the search has some problems
3980 with the blank space at the end */
3981 if (gtk_text_iter_forward_search (&iter, "--",
3982 GTK_TEXT_SEARCH_TEXT_ONLY,
3983 &match_start, NULL, NULL)) {
3984 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
3985 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
3987 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
3988 &match_start, &match_end, NULL)) {
3992 gtk_text_buffer_get_end_iter (priv->text_buffer, &iter);
3997 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3998 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
3999 if (has_new_signature) {
4001 gchar *full_signature = g_strconcat ((gtk_text_iter_starts_line (&iter)) ? "" : "\n",
4002 MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4004 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4005 g_free (full_signature);
4008 gtk_text_buffer_end_user_action (priv->text_buffer);
4011 static void update_branding (ModestMsgEditWindow *self,
4012 const gchar *new_account)
4014 ModestMsgEditWindowPrivate *priv;
4015 ModestAccountMgr *mgr;
4016 const GdkPixbuf *new_icon = NULL;
4017 gchar *new_label = NULL;
4018 gboolean show = FALSE;
4020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4022 mgr = modest_runtime_get_account_mgr ();
4024 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4026 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4027 gtk_widget_show (priv->brand_icon);
4030 gtk_widget_hide (priv->brand_icon);
4033 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4034 gtk_widget_show (priv->brand_label);
4038 gtk_widget_hide (priv->brand_label);
4042 gtk_widget_show (priv->brand_container);
4044 gtk_widget_hide (priv->brand_container);
4048 from_field_changed (HildonPickerButton *button,
4049 ModestMsgEditWindow *self)
4051 ModestMsgEditWindowPrivate *priv;
4052 gchar *old_account, *new_account;
4054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4056 old_account = priv->last_from_account;
4057 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4060 g_warning ("%s, could not get the new account", __FUNCTION__);
4064 /* If the From is the same do nothing */
4065 if (old_account && new_account && !strcmp (old_account, new_account))
4068 priv->last_from_account = new_account;
4070 update_signature (self, old_account, new_account);
4071 update_branding (self, new_account);
4075 typedef struct _MessageSettingsHelper {
4076 ModestMsgEditWindow *window;
4077 GSList *priority_group;
4078 GSList *format_group;
4079 GtkToggleButton *current_priority;
4080 GtkToggleButton *current_format;
4081 } MessageSettingsHelper;
4084 on_priority_toggle (GtkToggleButton *button,
4085 MessageSettingsHelper *helper)
4088 ModestMsgEditWindowPrivate *priv;
4090 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4091 if (gtk_toggle_button_get_active (button)) {
4093 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4094 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4095 if ((node_button != button) &&
4096 gtk_toggle_button_get_active (node_button)) {
4097 gtk_toggle_button_set_active (node_button, FALSE);
4100 helper->current_priority = button;
4102 gboolean found = FALSE;
4103 /* If no one is active, activate it again */
4104 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4105 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4106 if (gtk_toggle_button_get_active (node_button)) {
4112 gtk_toggle_button_set_active (button, TRUE);
4118 on_format_toggle (GtkToggleButton *button,
4119 MessageSettingsHelper *helper)
4122 ModestMsgEditWindowPrivate *priv;
4124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4125 if (gtk_toggle_button_get_active (button)) {
4127 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4128 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4129 if ((node_button != button) &&
4130 gtk_toggle_button_get_active (node_button)) {
4131 gtk_toggle_button_set_active (node_button, FALSE);
4134 helper->current_format = button;
4136 gboolean found = FALSE;
4137 /* If no one is active, activate it again */
4138 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4139 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4140 if (gtk_toggle_button_get_active (node_button)) {
4146 gtk_toggle_button_set_active (button, TRUE);
4153 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4158 GtkWidget *priority_hbox;
4159 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4160 GtkWidget *captioned;
4161 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4162 GtkWidget *format_hbox;
4163 GtkWidget *html_toggle, *text_toggle;
4164 ModestMsgEditWindowPrivate *priv;
4165 MessageSettingsHelper helper = {0,};
4167 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4169 helper.window = window;
4170 helper.priority_group = NULL;
4171 helper.format_group = NULL;
4173 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4174 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4176 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4177 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4178 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4179 vbox = gtk_vbox_new (FALSE, 0);
4180 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4181 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4182 gtk_container_add (GTK_CONTAINER (align), vbox);
4183 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4184 gtk_widget_show (align);
4185 gtk_widget_show (vbox);
4187 /* Priority toggles */
4188 priority_hbox = gtk_hbox_new (TRUE, 0);
4189 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4190 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4191 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4192 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4193 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4194 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4195 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4196 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4197 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4198 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4199 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4200 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4201 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4202 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4203 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4204 gtk_widget_show_all (priority_hbox);
4205 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4206 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4207 gtk_widget_show (captioned);
4208 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4210 /* format toggles */
4211 format_hbox = gtk_hbox_new (TRUE, 0);
4212 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4213 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4214 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4215 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4216 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4217 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4218 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4219 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4220 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4221 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4222 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4223 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4224 gtk_widget_show_all (format_hbox);
4225 gtk_widget_show (format_hbox);
4226 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4229 g_object_unref (title_sizegroup);
4230 g_object_unref (value_sizegroup);
4232 /* Set current values */
4233 switch (priv->priority_flags) {
4234 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4235 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4236 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4238 case TNY_HEADER_FLAG_LOW_PRIORITY:
4239 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4240 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4243 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4244 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4248 switch (modest_msg_edit_window_get_format (window)) {
4249 case MODEST_MSG_EDIT_FORMAT_TEXT:
4250 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4251 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4253 case MODEST_MSG_EDIT_FORMAT_HTML:
4255 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4256 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4260 /* Signal connects */
4261 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4262 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4263 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4264 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4265 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4267 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4268 GTK_WINDOW (dialog), GTK_WINDOW (window));
4270 /* Save settings if the user clicked on done */
4271 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4272 TnyHeaderFlags flags;
4273 ModestMsgEditFormat old_format, new_format;
4275 /* Set priority flags */
4276 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4277 if (priv->priority_flags != flags)
4278 modest_msg_edit_window_set_priority_flags (window, flags);
4280 /* Set edit format */
4281 old_format = modest_msg_edit_window_get_format (window);
4282 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4283 if (old_format != new_format) {
4284 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4285 modest_msg_edit_window_set_file_format (window, file_format);
4289 gtk_widget_destroy (dialog);
4290 g_slist_free (helper.priority_group);
4294 on_message_settings (GtkAction *action,
4295 ModestMsgEditWindow *window)
4297 modest_msg_edit_window_show_msg_settings_dialog (window);
4301 on_cc_button_toggled (HildonCheckButton *button,
4302 ModestMsgEditWindow *window)
4304 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4306 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4307 hildon_check_button_get_active (button));
4311 on_bcc_button_toggled (HildonCheckButton *button,
4312 ModestMsgEditWindow *window)
4314 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4316 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4317 hildon_check_button_get_active (button));
4321 setup_menu (ModestMsgEditWindow *self)
4323 ModestMsgEditWindowPrivate *priv = NULL;
4325 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4327 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4329 /* Settings menu buttons */
4330 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4331 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4333 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4334 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4335 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4337 priv->cc_button = hildon_check_button_new (0);
4338 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4339 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4341 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4343 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4344 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4345 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4346 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4348 priv->bcc_button = hildon_check_button_new (0);
4349 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4350 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4352 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4354 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4355 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4356 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4357 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4359 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4360 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4361 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4362 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4363 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4365 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4366 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4367 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4368 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4369 APP_MENU_CALLBACK (on_message_settings),
4371 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4372 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4377 emit_open_addressbook (GtkButton *button,
4378 ModestRecptEditor *editor)
4380 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4384 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4385 const gchar *label, GtkWidget *control)
4387 GtkWidget *abook_button;
4390 GtkWidget *label_widget;
4392 box = gtk_hbox_new (FALSE, 0);
4394 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4395 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4397 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4398 label_widget = gtk_label_new (label);
4399 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4400 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4402 gtk_container_add (GTK_CONTAINER (align), abook_button);
4403 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4404 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4405 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4406 if (title_size_group)
4407 gtk_size_group_add_widget (title_size_group, label_widget);
4408 if (value_size_group)
4409 gtk_size_group_add_widget (value_size_group, control);
4411 g_signal_connect (G_OBJECT (abook_button), "clicked",
4412 G_CALLBACK (emit_open_addressbook), control);
4418 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4420 ModestMsgEditWindowPrivate *priv = NULL;
4422 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4424 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4425 priv->max_chars_banner = NULL;