1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
38 #include <tny-camel-mem-stream.h>
39 #include <modest-account-protocol.h>
43 #include <modest-account-mgr.h>
44 #include <modest-account-mgr-helpers.h>
46 #include <widgets/modest-msg-edit-window.h>
47 #include <modest-selector-picker.h>
48 #include <widgets/modest-recpt-editor.h>
49 #include <widgets/modest-attachments-view.h>
51 #include <modest-runtime.h>
53 #include "modest-platform.h"
54 #include "modest-icon-names.h"
55 #include "modest-widget-memory.h"
56 #include "modest-window-priv.h"
57 #include "modest-mail-operation.h"
58 #include "modest-tny-platform-factory.h"
59 #include "modest-tny-msg.h"
60 #include "modest-tny-folder.h"
61 #include "modest-tny-account.h"
62 #include "modest-address-book.h"
63 #include "modest-text-utils.h"
64 #include <tny-simple-list.h>
65 #include <modest-wp-text-view.h>
66 #include <wptextbuffer.h>
67 #include <hildon/hildon-pannable-area.h>
68 #include <hildon/hildon-touch-selector.h>
69 #include <hildon/hildon-picker-dialog.h>
70 #include "modest-msg-edit-window-ui-dimming.h"
72 #include "modest-hildon-includes.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <hildon-widgets/hildon-color-chooser.h>
76 #include "widgets/modest-msg-edit-window-ui.h"
77 #ifdef MODEST_HAVE_HILDON0_WIDGETS
78 #include <libgnomevfs/gnome-vfs-mime-utils.h>
80 #include <libgnomevfs/gnome-vfs-mime.h>
82 #include <modest-utils.h>
83 #include "modest-maemo-utils.h"
84 #include <modest-ui-constants.h>
87 #define DEFAULT_FONT_SIZE 3
88 #define DEFAULT_FONT 2
89 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
90 #define DEFAULT_MAIN_VBOX_SPACING 6
91 #define SUBJECT_MAX_LENGTH 1000
92 #define IMAGE_MAX_WIDTH 560
93 #define DEFAULT_FONT_SCALE 1.5
94 #define ATTACHMENT_BUTTON_WIDTH 118
95 #define MAX_FROM_VALUE 36
96 #define MAX_BODY_LENGTH 128*1024
97 #define MAX_BODY_LINES 2048
99 static gboolean is_wp_text_buffer_started = FALSE;
101 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
102 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
103 static void modest_msg_edit_window_finalize (GObject *obj);
105 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
106 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
107 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
109 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
110 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
111 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
112 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
113 GtkTextIter *start, GtkTextIter *end,
115 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
116 static void body_insert_text (GtkTextBuffer *buffer,
117 GtkTextIter *location,
120 ModestMsgEditWindow *window);
121 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
122 static void subject_field_insert_text (GtkEditable *editable,
124 gint new_text_length,
126 ModestMsgEditWindow *window);
127 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
129 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
131 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
132 ModestRecptEditor *editor);
133 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
134 ModestMsgEditWindow *window);
136 /* ModestWindow methods implementation */
137 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
138 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
139 gboolean show_toolbar);
140 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
142 ModestMsgEditWindow *window);
143 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
144 static void subject_field_move_cursor (GtkEntry *entry,
145 GtkMovementStep step,
149 static void update_window_title (ModestMsgEditWindow *window);
152 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
153 ModestMsgEditWindow *window);
154 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
155 ModestMsgEditWindow *window);
156 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
158 GtkTextIter *match_start,
159 GtkTextIter *match_end);
161 static void remove_tags (WPTextBuffer *buffer);
163 static void on_account_removed (TnyAccountStore *account_store,
167 static void init_window (ModestMsgEditWindow *obj);
169 gboolean scroll_drag_timeout (gpointer userdata);
170 static void correct_scroll (ModestMsgEditWindow *w);
171 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
172 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
173 ModestMsgEditWindow *userdata);
174 static void text_buffer_mark_set (GtkTextBuffer *buffer,
177 ModestMsgEditWindow *userdata);
178 static void on_message_settings (GtkAction *action,
179 ModestMsgEditWindow *window);
180 static void setup_menu (ModestMsgEditWindow *self);
182 static void from_field_changed (HildonPickerButton *button,
183 ModestMsgEditWindow *self);
184 static void font_size_clicked (GtkToolButton *button,
185 ModestMsgEditWindow *window);
186 static void font_face_clicked (GtkToolButton *button,
187 ModestMsgEditWindow *window);
188 static void update_signature (ModestMsgEditWindow *self,
189 const gchar *old_account,
190 const gchar *new_account);
191 static void update_branding (ModestMsgEditWindow *self,
192 const gchar *new_account);
193 static GtkWidget *_create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
194 const gchar *label, GtkWidget *control);
195 static void max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref);
196 static void DEBUG_BUFFER (WPTextBuffer *buffer)
200 g_debug ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
202 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
203 while (!gtk_text_iter_is_end (&iter)) {
204 GString *output = g_string_new ("");
205 GSList *toggled_tags;
208 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
209 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
210 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
211 GtkTextTag *tag = (GtkTextTag *) node->data;
213 g_object_get (G_OBJECT (tag), "name", &name, NULL);
214 output = g_string_append (output, name);
215 g_string_append (output, " ");
217 output = g_string_append (output, "] OPENED [ ");
218 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
219 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
220 GtkTextTag *tag = (GtkTextTag *) node->data;
222 g_object_get (G_OBJECT (tag), "name", &name, NULL);
223 output = g_string_append (output, name);
224 g_string_append (output, " ");
226 output = g_string_append (output, "]\n");
227 g_debug ("%s", output->str);
228 g_string_free (output, TRUE);
229 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
231 g_debug ("END BUFFER");
235 static const GtkActionEntry hildon2_msg_edit_action_entries [] = {
236 { "MessageSettings", NULL, N_("mcen_me_message_settings"), NULL, NULL, G_CALLBACK (on_message_settings)},
240 /* static gboolean */
241 /* on_key_pressed (GtkWidget *self, */
242 /* GdkEventKey *event, */
243 /* gpointer user_data); */
245 /* list my signals */
252 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
253 struct _ModestMsgEditWindowPrivate {
255 GtkWidget *header_box;
257 ModestPairList *from_field_protos;
258 GtkWidget *from_field;
259 gchar *last_from_account;
260 gchar *original_account_name;
265 gchar *original_mailbox;
269 GtkWidget *bcc_field;
270 GtkWidget *subject_field;
271 GtkWidget *attachments_view;
272 GtkWidget *priority_icon;
273 GtkWidget *subject_box;
274 GtkWidget *send_button;
276 GtkWidget *cc_caption;
277 GtkWidget *bcc_caption;
278 gboolean update_caption_visibility;
279 GtkWidget *attachments_caption;
281 GtkTextBuffer *text_buffer;
283 GtkWidget *font_size_toolitem;
284 GtkWidget *font_face_toolitem;
285 GtkWidget *font_color_button;
286 GtkWidget *font_color_toolitem;
287 GSList *font_items_group;
288 GtkTreeModel *faces_model;
289 gint current_face_index;
290 GtkWidget *font_tool_button_label;
291 GtkTreeModel *sizes_model;
292 gint current_size_index;
293 GtkWidget *size_tool_button_label;
295 GtkWidget *find_toolbar;
298 GtkWidget *font_dialog;
301 guint correct_scroll_idle;
302 guint scroll_drag_timeout_id;
306 TnyList *attachments;
311 TnyHeaderFlags priority_flags;
313 gboolean can_undo, can_redo;
314 gulong clipboard_change_handler_id;
315 gulong default_clipboard_change_handler_id;
316 gulong account_removed_handler_id;
317 guint clipboard_owner_idle;
318 gchar *clipboard_text;
327 GtkWidget *cc_button;
328 GtkWidget *bcc_button;
330 GtkWidget *max_chars_banner;
332 GtkWidget *brand_icon;
333 GtkWidget *brand_label;
334 GtkWidget *brand_container;
337 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
338 MODEST_TYPE_MSG_EDIT_WINDOW, \
339 ModestMsgEditWindowPrivate))
341 static GtkWindowClass *parent_class = NULL;
343 /* uncomment the following if you have defined any signals */
344 /* static guint signals[LAST_SIGNAL] = {0}; */
347 modest_msg_edit_window_get_type (void)
349 static GType my_type = 0;
351 static const GTypeInfo my_info = {
352 sizeof(ModestMsgEditWindowClass),
353 NULL, /* base init */
354 NULL, /* base finalize */
355 (GClassInitFunc) modest_msg_edit_window_class_init,
356 NULL, /* class finalize */
357 NULL, /* class data */
358 sizeof(ModestMsgEditWindow),
360 (GInstanceInitFunc) modest_msg_edit_window_init,
363 my_type = g_type_register_static (MODEST_TYPE_HILDON2_WINDOW,
364 "ModestMsgEditWindow",
372 save_state (ModestWindow *self)
374 modest_widget_memory_save (modest_runtime_get_conf(),
375 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
380 restore_settings (ModestMsgEditWindow *self)
382 ModestConf *conf = NULL;
384 conf = modest_runtime_get_conf ();
386 /* Dim at start clipboard actions */
387 modest_widget_memory_restore (conf, G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
392 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
394 GObjectClass *gobject_class;
395 ModestWindowClass *modest_window_class;
396 gobject_class = (GObjectClass*) klass;
397 modest_window_class = (ModestWindowClass*) klass;
399 parent_class = g_type_class_peek_parent (klass);
400 gobject_class->finalize = modest_msg_edit_window_finalize;
402 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
403 modest_window_class->save_state_func = save_state;
404 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
406 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
410 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
412 ModestMsgEditWindowPrivate *priv;
413 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
415 priv->msg_body = NULL;
416 priv->from_field = NULL;
417 priv->to_field = NULL;
418 priv->cc_field = NULL;
419 priv->bcc_field = NULL;
420 priv->subject_field = NULL;
421 priv->attachments = TNY_LIST (tny_simple_list_new ());
422 priv->images = TNY_LIST (tny_simple_list_new ());
423 priv->images_size = 0;
424 priv->images_count = 0;
427 priv->cc_caption = NULL;
428 priv->bcc_caption = NULL;
429 priv->update_caption_visibility = FALSE;
431 priv->priority_flags = 0;
433 priv->find_toolbar = NULL;
434 priv->last_search = NULL;
436 priv->draft_msg = NULL;
437 priv->outbox_msg = NULL;
438 priv->msg_uid = NULL;
440 priv->can_undo = FALSE;
441 priv->can_redo = FALSE;
442 priv->clipboard_change_handler_id = 0;
443 priv->default_clipboard_change_handler_id = 0;
444 priv->account_removed_handler_id = 0;
445 priv->clipboard_owner_idle = 0;
446 priv->clipboard_text = NULL;
449 priv->scroll_drag_timeout_id = 0;
450 priv->correct_scroll_idle = 0;
451 priv->last_upper = 0.0;
453 priv->font_dialog = NULL;
454 priv->app_menu = NULL;
456 priv->references = NULL;
457 priv->in_reply_to = NULL;
458 priv->max_chars_banner = NULL;
460 if (!is_wp_text_buffer_started) {
461 is_wp_text_buffer_started = TRUE;
462 wp_text_buffer_library_init ();
467 hildon_program_add_window (hildon_program_get_instance(),
472 multimailbox_get_default_mailbox (const gchar *account_name)
474 gchar *transport_account;
475 gchar *result = NULL;
477 transport_account = modest_account_mgr_get_server_account_name (modest_runtime_get_account_mgr (),
479 TNY_ACCOUNT_TYPE_TRANSPORT);
480 if (transport_account) {
482 ModestProtocolRegistry *registry;
484 registry = modest_runtime_get_protocol_registry ();
486 proto = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), transport_account,
487 MODEST_ACCOUNT_PROTO, TRUE);
489 ModestProtocol *protocol =
490 modest_protocol_registry_get_protocol_by_name (registry,
491 MODEST_PROTOCOL_REGISTRY_TRANSPORT_PROTOCOLS,
493 if (MODEST_ACCOUNT_PROTOCOL (protocol)) {
494 ModestPairList *pair_list;
496 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
499 ModestPair *pair = (ModestPair *) pair_list->data;
500 result = g_strdup ((const gchar *) pair->first);
501 modest_pair_list_free (pair_list);
512 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
514 static ModestPairList*
515 get_transports (void)
517 GSList *transports = NULL;
519 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
520 GSList *accounts = modest_account_mgr_account_names (account_mgr,
521 TRUE /* only enabled accounts. */);
523 GSList *cursor = accounts;
525 gchar *account_name = cursor->data;
528 gchar *transport_account;
529 gboolean multi_mailbox = FALSE;
530 ModestProtocol *protocol = NULL;
532 if (modest_account_mgr_account_is_multimailbox (account_mgr, account_name, &protocol)) {
534 transport_account = modest_account_mgr_get_server_account_name
535 (modest_runtime_get_account_mgr (),
537 TNY_ACCOUNT_TYPE_TRANSPORT);
538 if (protocol && MODEST_IS_ACCOUNT_PROTOCOL (protocol)) {
539 ModestPairList *pair_list;
540 pair_list = modest_account_protocol_get_from_list (MODEST_ACCOUNT_PROTOCOL (protocol),
543 transports = g_slist_concat (transports, pair_list);
544 multi_mailbox = TRUE;
549 if (!multi_mailbox) {
550 gchar *from_string = NULL;
552 from_string = modest_account_mgr_get_from_string (account_mgr,
554 if (from_string && account_name) {
555 gchar *name = account_name;
556 ModestPair *pair = modest_pair_new ((gpointer) name,
557 (gpointer) from_string , TRUE);
558 transports = g_slist_prepend (transports, pair);
563 cursor = cursor->next;
565 g_slist_free (accounts); /* only free the accounts, not the elements,
566 * because they are used in the pairlist */
570 static void window_focus (GtkWindow *window,
574 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
578 scroll_drag_timeout (gpointer userdata)
580 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
581 ModestMsgEditWindowPrivate *priv;
583 /* It could happen that the window was already closed */
584 if (!GTK_WIDGET_VISIBLE (win))
587 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
589 correct_scroll_without_drag_check (win, TRUE);
591 priv->scroll_drag_timeout_id = 0;
597 correct_scroll_without_drag_check_idle (gpointer userdata)
599 ModestMsgEditWindow *w = (ModestMsgEditWindow *) userdata;
600 ModestMsgEditWindowPrivate *priv;
602 GdkRectangle rectangle;
603 gint offset_min, offset_max;
607 /* It could happen that the window was already closed */
608 if (!GTK_WIDGET_VISIBLE (w))
611 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
613 insert = gtk_text_buffer_get_insert (priv->text_buffer);
614 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
616 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
617 offset_min = priv->msg_body->allocation.y + rectangle.y;
618 offset_max = offset_min + rectangle.height;
620 vadj = hildon_pannable_area_get_vadjustment (HILDON_PANNABLE_AREA (priv->pannable));
621 offset_min = MAX (offset_min - 48, 0);
622 offset_max = MIN (offset_max + 48, vadj->upper);
624 gtk_adjustment_clamp_page (vadj, (gdouble) offset_min, (gdouble) offset_max);
626 priv->correct_scroll_idle = 0;
631 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
633 ModestMsgEditWindowPrivate *priv;
635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
637 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
640 if (priv->correct_scroll_idle > 0) {
644 priv->correct_scroll_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
645 (GSourceFunc) correct_scroll_without_drag_check_idle,
651 correct_scroll (ModestMsgEditWindow *w)
653 ModestMsgEditWindowPrivate *priv;
655 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
656 if (gtk_grab_get_current () == priv->msg_body) {
657 if (priv->scroll_drag_timeout_id == 0) {
658 priv->scroll_drag_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
660 (GSourceFunc) scroll_drag_timeout,
667 correct_scroll_without_drag_check (w, TRUE);
671 text_buffer_end_user_action (GtkTextBuffer *buffer,
672 ModestMsgEditWindow *userdata)
675 correct_scroll (userdata);
679 text_buffer_mark_set (GtkTextBuffer *buffer,
682 ModestMsgEditWindow *userdata)
684 gtk_text_buffer_begin_user_action (buffer);
685 gtk_text_buffer_end_user_action (buffer);
689 cut_clipboard_check (GtkTextView *text_view,
692 GtkTextBuffer *buffer;
694 buffer = gtk_text_view_get_buffer (text_view);
695 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
696 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
701 copy_clipboard_check (GtkTextView *text_view,
704 GtkTextBuffer *buffer;
706 buffer = gtk_text_view_get_buffer (text_view);
707 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
708 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
713 attachment_deleted (ModestAttachmentsView *attachments_view,
716 modest_msg_edit_window_remove_attachments (MODEST_MSG_EDIT_WINDOW (user_data),
721 body_size_request (GtkWidget *body,
725 /* Make sure the body always get at least 70 pixels */
726 if (req->height < 70)
731 connect_signals (ModestMsgEditWindow *obj)
733 ModestMsgEditWindowPrivate *priv;
735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
737 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
738 G_CALLBACK (text_buffer_refresh_attributes), obj);
739 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
740 G_CALLBACK (text_buffer_can_undo), obj);
741 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
742 G_CALLBACK (text_buffer_can_redo), obj);
743 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
744 G_CALLBACK (body_changed), obj);
745 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
746 G_CALLBACK (body_insert_text), obj);
747 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
748 G_CALLBACK (body_changed), obj);
749 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
750 G_CALLBACK (text_buffer_end_user_action), obj);
751 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
752 G_CALLBACK (text_buffer_mark_set), obj);
753 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
754 G_CALLBACK (text_buffer_apply_tag), obj);
755 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
756 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
757 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
758 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
759 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
760 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
762 g_signal_connect (G_OBJECT (priv->send_button), "clicked",
763 G_CALLBACK (modest_ui_actions_on_send), obj);
765 g_signal_connect (G_OBJECT (priv->from_field), "value-changed",
766 G_CALLBACK (from_field_changed), obj);
768 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
769 G_CALLBACK (msg_body_focus), obj);
770 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
771 G_CALLBACK (msg_body_focus), obj);
772 g_signal_connect (G_OBJECT (priv->msg_body), "size-request",
773 G_CALLBACK (body_size_request), obj);
774 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
775 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
776 "changed", G_CALLBACK (recpt_field_changed), obj);
777 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
778 "changed", G_CALLBACK (recpt_field_changed), obj);
779 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
780 "changed", G_CALLBACK (recpt_field_changed), obj);
781 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
782 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
783 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
785 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
786 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
788 priv->clipboard_change_handler_id =
789 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
790 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
791 priv->default_clipboard_change_handler_id =
792 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
793 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
795 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
796 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
797 g_signal_connect (G_OBJECT (priv->attachments_view), "delete", G_CALLBACK (attachment_deleted), obj);
801 init_wp_text_view_style ()
803 static gboolean initialized = FALSE;
806 gtk_rc_parse_string ("class \"WPTextView\" style \"fremantle-textview\"");
812 init_window (ModestMsgEditWindow *obj)
814 GtkWidget *to_caption, *subject_caption;
815 GtkWidget *main_vbox;
816 ModestMsgEditWindowPrivate *priv;
817 GtkActionGroup *action_group;
818 ModestWindowPrivate *parent_priv;
819 GdkPixbuf *window_icon = NULL;
820 GError *error = NULL;
822 GtkSizeGroup *title_size_group;
823 GtkSizeGroup *value_size_group;
824 GtkWidget *window_box;
825 GtkWidget *window_align;
826 #if (GTK_MINOR_VERSION >= 10)
827 GdkAtom deserialize_type;
829 GtkWidget *from_send_hbox;
830 GtkWidget *send_icon;
831 GtkWidget *attachments_label;
832 GtkWidget *branding_box;
834 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
835 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
837 parent_priv->ui_manager = gtk_ui_manager_new();
838 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
839 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
841 /* Add common actions */
842 gtk_action_group_add_actions (action_group,
843 modest_msg_edit_action_entries,
844 G_N_ELEMENTS (modest_msg_edit_action_entries),
846 gtk_action_group_add_actions (action_group,
847 hildon2_msg_edit_action_entries,
848 G_N_ELEMENTS (hildon2_msg_edit_action_entries),
850 gtk_action_group_add_toggle_actions (action_group,
851 modest_msg_edit_toggle_action_entries,
852 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
854 gtk_action_group_add_radio_actions (action_group,
855 modest_msg_edit_alignment_radio_action_entries,
856 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
858 G_CALLBACK (modest_ui_actions_on_change_justify),
860 gtk_action_group_add_radio_actions (action_group,
861 modest_msg_edit_priority_action_entries,
862 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
864 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
866 gtk_action_group_add_radio_actions (action_group,
867 modest_msg_edit_file_format_action_entries,
868 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
869 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
870 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
872 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
873 g_object_unref (action_group);
875 /* Load the UI definition */
876 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
879 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
880 g_clear_error (&error);
883 /* Add accelerators */
884 gtk_window_add_accel_group (GTK_WINDOW (obj),
885 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
887 parent_priv->menubar = NULL;
889 title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
890 value_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
892 /* Note: This ModestPairList* must exist for as long as the picker
893 * that uses it, because the ModestSelectorPicker uses the ID opaquely,
894 * so it can't know how to manage its memory. */
895 priv->from_field = modest_selector_picker_new (MODEST_EDITABLE_SIZE,
896 HILDON_BUTTON_ARRANGEMENT_HORIZONTAL,
898 modest_selector_picker_set_value_max_chars (MODEST_SELECTOR_PICKER (priv->from_field), MAX_FROM_VALUE);
899 modest_maemo_utils_set_hbutton_layout (title_size_group, NULL,
900 _("mail_va_from"), priv->from_field);
901 hildon_button_set_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5, 1.0, 1.0);
902 hildon_button_set_title_alignment (HILDON_BUTTON (priv->from_field), 0.0, 0.5);
903 hildon_button_set_value_alignment (HILDON_BUTTON (priv->from_field), 1.0, 0.5);
905 priv->to_field = modest_recpt_editor_new ();
906 priv->cc_field = modest_recpt_editor_new ();
907 priv->bcc_field = modest_recpt_editor_new ();
908 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->to_field), FALSE);
909 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->cc_field), FALSE);
910 modest_recpt_editor_set_show_abook_button (MODEST_RECPT_EDITOR (priv->bcc_field), FALSE);
911 priv->subject_box = gtk_hbox_new (FALSE, MODEST_MARGIN_NONE);
912 priv->priority_icon = gtk_image_new ();
913 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->priority_icon, FALSE, FALSE, 0);
914 priv->subject_field = hildon_entry_new (MODEST_EDITABLE_SIZE);
915 gtk_entry_set_max_length (GTK_ENTRY (priv->subject_field) ,SUBJECT_MAX_LENGTH);
916 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
917 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
918 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
919 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
920 priv->attachments_view = modest_attachments_view_new (NULL);
921 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
922 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
924 priv->header_box = gtk_vbox_new (FALSE, 0);
926 to_caption = _create_addressbook_box
927 (title_size_group, value_size_group,
928 _("mail_va_to"), priv->to_field);
929 priv->cc_caption = _create_addressbook_box
930 (title_size_group, value_size_group,
931 _("mail_va_cc"), priv->cc_field);
932 priv->bcc_caption = _create_addressbook_box
933 (title_size_group, value_size_group,
934 _("mail_va_hotfix1"), priv->bcc_field);
935 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
936 _("mail_va_subject"), FALSE, priv->subject_box);
937 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
938 _("mail_va_attachment"),
940 priv->attachments_view,
941 HILDON_SIZE_AUTO_WIDTH |
942 HILDON_SIZE_AUTO_HEIGHT);
943 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
944 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
947 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
948 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
949 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
950 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
952 g_object_unref (title_size_group);
953 g_object_unref (value_size_group);
955 priv->brand_icon = gtk_image_new ();
956 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
957 priv->brand_label = gtk_label_new (NULL);
958 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
959 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
960 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
961 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
963 from_send_hbox = gtk_hbox_new (FALSE, 0);
964 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
965 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
967 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
968 gtk_widget_show (branding_box);
969 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
970 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
972 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
973 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
974 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
975 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
978 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
979 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
980 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
981 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
982 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
983 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
984 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
985 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
987 init_wp_text_view_style ();
989 priv->msg_body = modest_wp_text_view_new ();
992 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
993 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
994 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
995 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
996 #if (GTK_MINOR_VERSION >= 10)
997 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
998 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1000 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1001 deserialize_type, TRUE);
1003 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1005 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1006 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1008 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1010 priv->pannable = hildon_pannable_area_new ();
1012 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1014 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1015 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1016 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1018 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1019 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1020 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1022 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1023 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1025 window_box = gtk_vbox_new (FALSE, 0);
1026 gtk_container_add (GTK_CONTAINER(obj), window_box);
1028 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1030 /* Set window icon */
1031 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1033 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1034 g_object_unref (window_icon);
1039 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1041 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1043 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1044 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1045 priv->clipboard_change_handler_id))
1046 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1047 priv->clipboard_change_handler_id);
1048 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1049 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1050 priv->default_clipboard_change_handler_id))
1051 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1052 priv->default_clipboard_change_handler_id);
1054 if (priv->account_removed_handler_id &&
1055 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1056 priv->account_removed_handler_id))
1057 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1058 priv->account_removed_handler_id);
1062 modest_msg_edit_window_finalize (GObject *obj)
1064 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1066 if (priv->max_chars_banner) {
1067 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1068 priv->max_chars_banner = FALSE;
1071 /* Sanity check: shouldn't be needed, the window mgr should
1072 call this function before */
1073 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1075 if (priv->font_dialog != NULL) {
1076 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1079 if (priv->clipboard_text != NULL) {
1080 g_free (priv->clipboard_text);
1081 priv->clipboard_text = NULL;
1084 if (priv->draft_msg != NULL) {
1085 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1086 if (TNY_IS_HEADER (header)) {
1087 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1088 modest_window_mgr_unregister_header (mgr, header);
1090 g_object_unref (priv->draft_msg);
1091 priv->draft_msg = NULL;
1093 if (priv->outbox_msg != NULL) {
1094 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1095 if (TNY_IS_HEADER (header)) {
1096 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1097 modest_window_mgr_unregister_header (mgr, header);
1099 g_object_unref (priv->outbox_msg);
1100 priv->outbox_msg = NULL;
1102 if (priv->correct_scroll_idle > 0) {
1103 g_source_remove (priv->correct_scroll_idle);
1104 priv->correct_scroll_idle = 0;
1106 if (priv->scroll_drag_timeout_id > 0) {
1107 g_source_remove (priv->scroll_drag_timeout_id);
1108 priv->scroll_drag_timeout_id = 0;
1110 if (priv->clipboard_owner_idle > 0) {
1111 g_source_remove (priv->clipboard_owner_idle);
1112 priv->clipboard_owner_idle = 0;
1114 if (priv->original_account_name)
1115 g_free (priv->original_account_name);
1116 if (priv->original_mailbox)
1117 g_free (priv->original_mailbox);
1118 g_free (priv->msg_uid);
1119 g_free (priv->last_search);
1120 g_free (priv->references);
1121 g_free (priv->in_reply_to);
1122 g_object_unref (priv->attachments);
1123 g_object_unref (priv->images);
1125 /* This had to stay alive for as long as the picker that used it: */
1126 modest_pair_list_free (priv->from_field_protos);
1128 G_OBJECT_CLASS(parent_class)->finalize (obj);
1132 pixbuf_size_prepared (GdkPixbufLoader *loader,
1135 ModestMsgEditWindow *self)
1137 gint new_height, new_width;
1140 new_height = height;
1144 if (width > IMAGE_MAX_WIDTH) {
1145 new_height = height * IMAGE_MAX_WIDTH / width;
1146 new_width = IMAGE_MAX_WIDTH;
1149 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1153 pixbuf_from_stream (TnyStream *stream,
1154 const gchar *mime_type,
1155 guint64 *stream_size,
1156 ModestMsgEditWindow *self)
1158 GdkPixbufLoader *loader;
1161 GError *error = NULL;
1165 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1167 if (loader == NULL) {
1172 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1174 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1176 tny_stream_reset (TNY_STREAM (stream));
1177 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1178 unsigned char read_buffer[128];
1180 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1182 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1185 /* Allow some UI responsiveness */
1186 while (gtk_events_pending ())
1187 gtk_main_iteration ();
1189 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1191 gdk_pixbuf_loader_close (loader, &error);
1194 g_error_free (error);
1195 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1197 g_object_ref (pixbuf);
1198 g_object_unref (loader);
1203 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1204 GdkPixbuf *new_pixbuf;
1206 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1207 gdk_pixbuf_get_width (pixbuf);
1208 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1209 g_object_unref (pixbuf);
1210 pixbuf = new_pixbuf;
1214 *stream_size = size;
1220 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1222 ModestMsgEditWindowPrivate *priv;
1225 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1227 g_object_ref (self);
1228 for (iter = tny_list_create_iterator (attachments);
1229 !tny_iterator_is_done (iter);
1230 tny_iterator_next (iter)) {
1231 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1232 const gchar *cid = tny_mime_part_get_content_id (part);
1233 const gchar *mime_type = tny_mime_part_get_content_type (part);
1234 if ((cid != NULL)&&(mime_type != NULL)) {
1235 guint64 stream_size;
1236 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1237 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1240 g_object_unref (stream);
1242 if (pixbuf != NULL) {
1243 priv->images_count ++;
1244 priv->images_size += stream_size;
1245 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1246 g_object_unref (pixbuf);
1249 g_object_unref (part);
1251 g_object_unref (iter);
1252 g_object_unref (self);
1256 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1258 TnyMimePart *parent = NULL;
1259 const gchar *content_type = NULL;
1260 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1262 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1264 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1265 parent = g_object_ref (msg);
1266 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1267 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1270 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1271 iter = tny_list_create_iterator (parts);
1272 while (!tny_iterator_is_done (iter)) {
1274 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1275 content_type = tny_mime_part_get_content_type (part);
1276 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1280 g_object_unref (part);
1282 tny_iterator_next (iter);
1284 g_object_unref (iter);
1285 g_object_unref (parts);
1288 if (parent != NULL) {
1289 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1292 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1293 iter = tny_list_create_iterator (parts);
1294 while (!tny_iterator_is_done (iter)) {
1296 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1297 content_type = tny_mime_part_get_content_type (part);
1298 if (content_type && g_str_has_prefix (content_type, "image/")) {
1299 tny_list_prepend (priv->images, (GObject *) part);
1301 g_object_unref (part);
1302 tny_iterator_next (iter);
1304 g_object_unref (iter);
1305 g_object_unref (parts);
1306 g_object_unref (parent);
1311 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1314 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1316 for (iter = tny_list_create_iterator (attachments) ;
1317 !tny_iterator_is_done (iter);
1318 tny_iterator_next (iter)) {
1319 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1320 const gchar *cid = tny_mime_part_get_content_id (part);
1322 char *invalid = NULL;
1323 gint int_cid = strtol (cid, &invalid, 10);
1324 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1325 priv->next_cid = int_cid + 1;
1328 g_object_unref (part);
1330 g_object_unref (iter);
1334 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1337 gchar *to, *cc, *bcc, *subject;
1339 ModestMsgEditWindowPrivate *priv;
1340 ModestWindowPrivate *parent_priv;
1342 TnyHeaderFlags priority_flags;
1343 TnyFolder *msg_folder;
1344 gboolean is_html = FALSE;
1345 gboolean field_view_set;
1347 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1348 g_return_if_fail (TNY_IS_MSG (msg));
1350 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1351 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1353 header = tny_msg_get_header (msg);
1354 to = tny_header_dup_to (header);
1355 cc = tny_header_dup_cc (header);
1356 bcc = tny_header_dup_bcc (header);
1357 subject = tny_header_dup_subject (header);
1359 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1360 priority_flags = tny_header_get_priority (header);
1363 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1365 field_view_set = TRUE;
1367 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1368 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1369 gtk_widget_show (priv->cc_caption);
1370 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1371 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1372 gtk_widget_hide (priv->cc_caption);
1373 field_view_set = FALSE;
1375 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1377 field_view_set = TRUE;
1379 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1380 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1381 gtk_widget_show (priv->bcc_caption);
1382 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1383 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1384 gtk_widget_hide (priv->bcc_caption);
1385 field_view_set = FALSE;
1387 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1391 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1392 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1395 update_window_title (self);
1397 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1398 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1400 if ((body == NULL)||(body[0] == '\0')) {
1402 body = modest_text_utils_convert_to_html ("");
1405 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1406 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1409 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1412 /* Add attachments to the view */
1413 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1414 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1415 if (tny_list_get_length (priv->attachments) == 0) {
1416 gtk_widget_hide (priv->attachments_caption);
1418 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1419 gtk_widget_show_all (priv->attachments_caption);
1421 get_related_images (self, msg);
1422 update_next_cid (self, priv->attachments);
1423 update_next_cid (self, priv->images);
1424 replace_with_images (self, priv->images);
1426 if (preserve_is_rich && !is_html) {
1427 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1428 /* Get the default format required from configuration */
1429 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1430 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1433 /* Set the default focus depending on having already a To: field or not */
1434 if ((!to)||(*to == '\0')) {
1435 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1437 gtk_widget_grab_focus (priv->msg_body);
1440 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1442 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1443 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1445 modest_msg_edit_window_set_modified (self, FALSE);
1447 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1448 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1449 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1450 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1452 if (priv->msg_uid) {
1453 g_free (priv->msg_uid);
1454 priv->msg_uid = NULL;
1457 /* we should set a reference to the incoming message if it is a draft */
1458 msg_folder = tny_msg_get_folder (msg);
1460 if (modest_tny_folder_is_local_folder (msg_folder)) {
1461 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1462 if (type == TNY_FOLDER_TYPE_INVALID)
1463 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1465 if (type == TNY_FOLDER_TYPE_DRAFTS)
1466 priv->draft_msg = g_object_ref(msg);
1467 if (type == TNY_FOLDER_TYPE_OUTBOX)
1468 priv->outbox_msg = g_object_ref(msg);
1469 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1471 g_object_unref (msg_folder);
1482 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1484 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1485 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1486 GtkWidget *placeholder;
1487 GtkWidget *tool_item;
1492 GtkWidget *sizes_menu;
1493 GtkWidget *fonts_menu;
1499 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1500 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1501 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1502 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1504 /* Font color placeholder */
1505 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1506 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1509 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1510 priv->font_color_button = hildon_color_button_new ();
1511 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1512 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1513 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1514 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1515 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1516 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1517 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1518 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1520 G_CALLBACK (modest_msg_edit_window_color_button_change),
1523 /* Font size and face placeholder */
1524 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1525 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1527 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1528 priv->size_tool_button_label = gtk_label_new (NULL);
1529 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1530 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1531 size_text, "</span>", NULL);
1532 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1533 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1535 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1536 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1537 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1538 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1539 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1540 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1541 gtk_widget_set_sensitive (arrow, FALSE);
1542 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1543 sizes_menu = gtk_menu_new ();
1544 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1545 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1548 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1549 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1551 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1555 if (wp_font_size[size_index] == 12)
1556 priv->current_size_index = size_index;
1560 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1561 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1562 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1563 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1564 priv->font_size_toolitem = tool_item;
1567 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1568 priv->font_tool_button_label = gtk_label_new (NULL);
1569 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1570 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1571 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1573 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1574 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1575 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1576 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1577 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1578 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1579 gtk_widget_set_sensitive (arrow, FALSE);
1580 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1581 fonts_menu = gtk_menu_new ();
1582 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1583 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1586 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1588 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1589 0, wp_get_font_name (font_index),
1592 if (font_index == DEFAULT_FONT)
1593 priv->current_face_index = font_index;
1595 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1596 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1597 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1598 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1599 priv->font_face_toolitem = tool_item;
1601 /* Set expand and homogeneous for remaining items */
1602 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1603 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1604 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1605 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1606 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1607 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1609 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1610 will not show the tool items added to the placeholders) */
1611 gtk_widget_show_all (parent_priv->toolbar);
1613 /* Set the no show all *after* showing all items. We do not
1614 want the toolbar to be shown with a show all because it
1615 could go agains the gconf setting regarding showing or not
1616 the toolbar of the editor window */
1617 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1623 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1626 ModestWindowPrivate *parent_priv;
1627 ModestMsgEditWindowPrivate *priv;
1628 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1629 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1630 ModestWindowMgr *mgr = NULL;
1632 g_return_val_if_fail (msg, NULL);
1633 g_return_val_if_fail (account_name, NULL);
1635 mgr = modest_runtime_get_window_mgr ();
1637 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1639 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1640 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1642 /* Menubar. Update the state of some toggles */
1643 priv->from_field_protos = get_transports ();
1644 priv->original_mailbox = NULL;
1645 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1646 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1647 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1648 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1649 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1650 priv->original_mailbox = g_strdup (mailbox);
1651 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1652 /* We set the first mailbox as the active mailbox */
1653 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1654 if (priv->original_mailbox != NULL)
1655 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1656 (gpointer) priv->original_mailbox);
1658 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1659 (gpointer) account_name);
1661 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1663 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1664 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1665 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1667 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1668 hildon_touch_selector_get_current_text
1669 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1670 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1671 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1674 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1676 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1678 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1679 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1681 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1683 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1684 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1685 /* Add common dimming rules */
1686 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1687 modest_msg_edit_window_toolbar_dimming_entries,
1688 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1689 MODEST_WINDOW (obj));
1690 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1691 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1692 MODEST_WINDOW (obj));
1693 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1694 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1695 MODEST_WINDOW (obj));
1696 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1697 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1698 MODEST_WINDOW (obj));
1699 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1700 G_CALLBACK (modest_ui_dimming_rules_on_send),
1701 MODEST_WINDOW (obj));
1702 /* Insert dimming rules group for this window */
1703 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1704 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1706 /* Setup app menu */
1707 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1709 /* Checks the dimming rules */
1710 g_object_unref (toolbar_rules_group);
1711 g_object_unref (clipboard_rules_group);
1712 gtk_widget_hide (priv->priority_icon);
1713 gtk_widget_queue_resize (priv->subject_box);
1714 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1716 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1718 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1719 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1720 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1721 priv->update_caption_visibility = TRUE;
1723 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1725 /* Track account-removed signal, this window should be closed
1726 in the case we're creating a mail associated to the account
1728 priv->account_removed_handler_id =
1729 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1731 G_CALLBACK(on_account_removed),
1734 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1736 return (ModestWindow*) obj;
1740 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1742 GString **string_buffer = (GString **) user_data;
1744 *string_buffer = g_string_append (*string_buffer, buffer);
1750 * @result: A new string which should be freed with g_free().
1753 get_formatted_data (ModestMsgEditWindow *edit_window)
1755 ModestMsgEditWindowPrivate *priv;
1756 GString *string_buffer = g_string_new ("");
1758 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1760 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1762 modest_text_utils_hyperlinkify (string_buffer);
1764 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1766 return g_string_free (string_buffer, FALSE);
1771 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1774 const gchar *account_name;
1775 ModestMsgEditWindowPrivate *priv;
1776 TnyIterator *att_iter;
1777 const gchar *picker_active_id;
1779 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1781 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1783 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1784 g_return_val_if_fail (picker_active_id, NULL);
1785 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1787 /* don't free these (except from) */
1788 data = g_slice_new0 (MsgData);
1789 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1790 data->account_name = g_strdup (account_name);
1791 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1792 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1793 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1794 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1795 data->references = g_strdup (priv->references);
1796 data->in_reply_to = g_strdup (priv->in_reply_to);
1797 if (priv->draft_msg) {
1798 data->draft_msg = g_object_ref (priv->draft_msg);
1799 } else if (priv->outbox_msg) {
1800 data->draft_msg = g_object_ref (priv->outbox_msg);
1802 data->draft_msg = NULL;
1805 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1807 gtk_text_buffer_get_bounds (buf, &b, &e);
1808 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1810 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1811 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1813 data->html_body = NULL;
1815 /* deep-copy the data */
1816 att_iter = tny_list_create_iterator (priv->attachments);
1817 data->attachments = NULL;
1818 while (!tny_iterator_is_done (att_iter)) {
1819 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1820 if (!(TNY_IS_MIME_PART(part))) {
1821 g_warning ("strange data in attachment list");
1822 g_object_unref (part);
1823 tny_iterator_next (att_iter);
1826 data->attachments = g_list_append (data->attachments,
1828 tny_iterator_next (att_iter);
1830 g_object_unref (att_iter);
1832 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1833 att_iter = tny_list_create_iterator (priv->images);
1834 data->images = NULL;
1835 while (!tny_iterator_is_done (att_iter)) {
1836 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1838 if (!(TNY_IS_MIME_PART(part))) {
1839 g_warning ("strange data in attachment list");
1840 g_object_unref (part);
1841 tny_iterator_next (att_iter);
1844 cid = tny_mime_part_get_content_id (part);
1846 gchar *image_tag_id;
1847 GtkTextTag *image_tag;
1849 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1850 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1851 g_free (image_tag_id);
1853 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1855 ((gtk_text_iter_has_tag (&iter, image_tag))||
1856 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1857 data->images = g_list_append (data->images,
1858 g_object_ref (part));
1860 g_object_unref (part);
1861 tny_iterator_next (att_iter);
1863 g_object_unref (att_iter);
1865 data->priority_flags = priv->priority_flags;
1872 unref_gobject (GObject *obj, gpointer data)
1874 if (!G_IS_OBJECT(obj))
1876 g_object_unref (obj);
1880 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1883 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1891 g_free (data->from);
1892 g_free (data->subject);
1893 g_free (data->plain_body);
1894 g_free (data->html_body);
1895 g_free (data->account_name);
1896 g_free (data->references);
1897 g_free (data->in_reply_to);
1899 if (data->draft_msg != NULL) {
1900 g_object_unref (data->draft_msg);
1901 data->draft_msg = NULL;
1904 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1905 g_list_free (data->attachments);
1906 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1907 g_list_free (data->images);
1909 g_slice_free (MsgData, data);
1913 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1915 guint64 *parts_size)
1917 ModestMsgEditWindowPrivate *priv;
1919 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1921 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1923 /* TODO: add images */
1924 *parts_size += priv->images_size;
1925 *parts_count += priv->images_count;
1930 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1933 ModestMsgEditWindowPrivate *priv = NULL;
1934 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1936 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1938 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1940 return MODEST_MSG_EDIT_FORMAT_HTML;
1942 return MODEST_MSG_EDIT_FORMAT_TEXT;
1946 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1947 ModestMsgEditFormat format)
1949 ModestMsgEditWindowPrivate *priv;
1950 ModestWindowPrivate *parent_priv;
1952 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1953 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1954 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1957 case MODEST_MSG_EDIT_FORMAT_HTML:
1958 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1959 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1961 case MODEST_MSG_EDIT_FORMAT_TEXT:
1962 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1963 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1966 g_return_if_reached ();
1970 ModestMsgEditFormatState *
1971 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1973 ModestMsgEditFormatState *format_state = NULL;
1974 ModestMsgEditWindowPrivate *priv;
1975 WPTextBufferFormat *buffer_format;
1977 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1979 buffer_format = g_new0 (WPTextBufferFormat, 1);
1980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1982 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1984 format_state = g_new0 (ModestMsgEditFormatState, 1);
1985 format_state->bold = buffer_format->bold&0x1;
1986 format_state->italics = buffer_format->italic&0x1;
1987 format_state->bullet = buffer_format->bullet&0x1;
1988 format_state->color = buffer_format->color;
1989 format_state->font_size = buffer_format->font_size;
1990 format_state->font_family = wp_get_font_name (buffer_format->font);
1991 format_state->justification = buffer_format->justification;
1992 g_free (buffer_format);
1994 return format_state;
1999 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2000 const ModestMsgEditFormatState *format_state)
2002 ModestMsgEditWindowPrivate *priv;
2003 WPTextBufferFormat *buffer_format;
2004 WPTextBufferFormat *current_format;
2006 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2007 g_return_if_fail (format_state != NULL);
2009 buffer_format = g_new0 (WPTextBufferFormat, 1);
2010 current_format = g_new0 (WPTextBufferFormat, 1);
2012 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2013 gtk_widget_grab_focus (priv->msg_body);
2014 buffer_format->bold = (format_state->bold != FALSE);
2015 buffer_format->italic = (format_state->italics != FALSE);
2016 buffer_format->color = format_state->color;
2017 buffer_format->font_size = format_state->font_size;
2018 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2019 buffer_format->justification = format_state->justification;
2020 buffer_format->bullet = format_state->bullet;
2022 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2024 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2025 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2026 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2027 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2028 buffer_format->cs.font = (buffer_format->font != current_format->font);
2029 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2030 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2032 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2033 if (buffer_format->cs.bold) {
2034 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2035 GINT_TO_POINTER (buffer_format->bold&0x1));
2037 if (buffer_format->cs.italic) {
2038 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2039 GINT_TO_POINTER (buffer_format->italic&0x1));
2041 if (buffer_format->cs.color) {
2042 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2043 GINT_TO_POINTER (&(buffer_format->color)));
2045 if (buffer_format->cs.font_size) {
2046 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2047 GINT_TO_POINTER (buffer_format->font_size));
2049 if (buffer_format->cs.justification) {
2050 switch (buffer_format->justification) {
2051 case GTK_JUSTIFY_LEFT:
2052 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2053 GINT_TO_POINTER(TRUE));
2055 case GTK_JUSTIFY_CENTER:
2056 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2057 GINT_TO_POINTER(TRUE));
2059 case GTK_JUSTIFY_RIGHT:
2060 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2061 GINT_TO_POINTER(TRUE));
2068 if (buffer_format->cs.font) {
2069 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2070 GINT_TO_POINTER (buffer_format->font));
2072 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2073 if (buffer_format->cs.bullet) {
2074 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2075 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2077 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2079 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2081 g_free (buffer_format);
2082 g_free (current_format);
2084 /* Check dimming rules */
2085 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2086 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2090 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2092 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2094 ModestWindowPrivate *parent_priv;
2095 ModestMsgEditWindowPrivate *priv;
2097 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2098 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2100 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2101 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2102 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2103 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2105 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2106 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2107 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2110 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2112 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2113 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2115 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2116 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2118 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2119 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2122 switch (buffer_format->justification)
2124 case GTK_JUSTIFY_LEFT:
2125 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2127 case GTK_JUSTIFY_CENTER:
2128 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2130 case GTK_JUSTIFY_RIGHT:
2131 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2138 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2140 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2141 G_CALLBACK (modest_msg_edit_window_color_button_change),
2143 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2144 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2145 G_CALLBACK (modest_msg_edit_window_color_button_change),
2148 if (priv->current_size_index != buffer_format->font_size) {
2152 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2153 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2157 priv->current_size_index = buffer_format->font_size;
2159 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2160 markup = g_strconcat ("<span font_family='Sans'>",
2161 size_text, "</span>", NULL);
2163 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2167 gtk_tree_path_free (path);
2170 if (priv->current_face_index != buffer_format->font) {
2174 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2175 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2179 priv->current_face_index = buffer_format->font;
2180 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2181 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2182 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2189 g_free (buffer_format);
2193 #ifdef MODEST_HILDON_VERSION_0
2195 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2198 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2199 ModestMsgEditWindowPrivate *priv;
2200 GtkWidget *dialog = NULL;
2202 GdkColor *new_color = NULL;
2204 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2205 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2207 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2208 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2209 g_free (buffer_format);
2211 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2212 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2213 if (new_color != NULL) {
2214 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2215 (gpointer) new_color);
2218 gtk_widget_destroy (dialog);
2223 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2226 ModestMsgEditWindowPrivate *priv;
2227 GtkWidget *dialog = NULL;
2229 GdkColor *old_color = NULL;
2230 const GdkColor *new_color = NULL;
2232 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2233 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2235 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2236 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2238 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2239 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2240 if (new_color != NULL)
2241 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2243 gtk_widget_destroy (dialog);
2249 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2252 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2253 ModestMsgEditWindowPrivate *priv;
2254 GtkWidget *dialog = NULL;
2256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2257 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2259 dialog = hildon_color_chooser_new ();
2260 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2261 g_free (buffer_format);
2263 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2265 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2266 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2269 gtk_widget_destroy (dialog);
2274 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2277 ModestMsgEditWindowPrivate *priv;
2278 GtkWidget *dialog = NULL;
2279 GdkColor *old_color = NULL;
2281 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2282 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2284 dialog = hildon_color_chooser_new ();
2285 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2287 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2289 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2290 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2292 gtk_widget_destroy (dialog);
2295 #endif /*!MODEST_HILDON_VERSION_0*/
2300 create_stream_for_uri (const gchar* uri)
2305 TnyStream *result = NULL;
2307 GnomeVFSHandle *handle = NULL;
2308 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2309 if (test == GNOME_VFS_OK) {
2310 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2311 /* Streams over OBEX (Bluetooth) are not seekable but
2312 * we expect them to be (we might need to read them
2313 * several times). So if this is a Bluetooth URI just
2314 * read the whole file into memory (this is not a fast
2315 * protocol so we can assume that these files are not
2316 * going to be very big) */
2317 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2318 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2319 TnyStream *memstream = tny_camel_mem_stream_new ();
2320 tny_stream_write_to_stream (vfssstream, memstream);
2321 g_object_unref (vfssstream);
2324 result = vfssstream;
2332 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2335 ModestMsgEditWindowPrivate *priv;
2336 GtkWidget *dialog = NULL;
2338 GSList *uris = NULL;
2339 GSList *uri_node = NULL;
2341 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2343 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2344 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2345 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2347 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2349 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2350 GTK_WINDOW (dialog), GTK_WINDOW (window));
2352 response = gtk_dialog_run (GTK_DIALOG (dialog));
2354 case GTK_RESPONSE_OK:
2356 gchar *current_folder;
2357 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2358 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2359 if (current_folder && current_folder != '\0') {
2361 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2362 current_folder, &err);
2364 g_debug ("Error storing latest used folder: %s", err->message);
2368 g_free (current_folder);
2374 gtk_widget_destroy (dialog);
2376 g_object_ref (window);
2377 /* The operation could take some time so allow the dialog to be closed */
2378 while (gtk_events_pending ())
2379 gtk_main_iteration ();
2381 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2383 GnomeVFSHandle *handle = NULL;
2384 GnomeVFSResult result;
2385 GtkTextIter position;
2386 GtkTextMark *insert_mark;
2388 uri = (const gchar *) uri_node->data;
2389 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2390 if (result == GNOME_VFS_OK) {
2392 GnomeVFSFileInfo *info;
2393 gchar *filename, *basename, *escaped_filename;
2394 TnyMimePart *mime_part;
2396 const gchar *mime_type = NULL;
2397 GnomeVFSURI *vfs_uri;
2398 guint64 stream_size;
2400 gnome_vfs_close (handle);
2401 vfs_uri = gnome_vfs_uri_new (uri);
2403 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2404 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2405 g_free (escaped_filename);
2406 gnome_vfs_uri_unref (vfs_uri);
2407 info = gnome_vfs_file_info_new ();
2409 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2410 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2412 mime_type = gnome_vfs_file_info_get_mime_type (info);
2414 mime_part = tny_platform_factory_new_mime_part
2415 (modest_runtime_get_platform_factory ());
2417 TnyStream *stream = create_stream_for_uri (uri);
2419 if (stream == NULL) {
2421 modest_platform_information_banner (NULL, NULL,
2422 _FM("sfil_ib_opening_not_allowed"));
2424 g_object_unref (mime_part);
2425 gnome_vfs_file_info_unref (info);
2429 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2431 content_id = g_strdup_printf ("%d", priv->next_cid);
2432 tny_mime_part_set_content_id (mime_part, content_id);
2433 g_free (content_id);
2436 basename = g_path_get_basename (filename);
2437 tny_mime_part_set_filename (mime_part, basename);
2440 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2442 if (pixbuf != NULL) {
2443 priv->images_size += stream_size;
2444 priv->images_count ++;
2445 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2446 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2447 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2448 tny_mime_part_get_content_id (mime_part), pixbuf);
2449 g_object_unref (pixbuf);
2451 tny_list_prepend (priv->images, (GObject *) mime_part);
2452 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2454 modest_platform_information_banner (NULL, NULL,
2455 _("mail_ib_file_operation_failed"));
2459 g_object_unref (mime_part);
2460 gnome_vfs_file_info_unref (info);
2464 g_object_unref (window);
2468 on_attach_file_response (GtkDialog *dialog,
2472 GSList *uris = NULL;
2474 GnomeVFSFileSize total_size, allowed_size;
2475 ModestMsgEditWindow *window;
2476 ModestMsgEditWindowPrivate *priv;
2481 case GTK_RESPONSE_OK:
2483 gchar *current_folder;
2485 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2486 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2487 if (current_folder && current_folder != '\0') {
2489 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2490 current_folder, &err);
2492 g_debug ("Error storing latest used folder: %s", err->message);
2496 g_free (current_folder);
2503 window = MODEST_MSG_EDIT_WINDOW (user_data);
2504 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2506 /* allowed size is the maximum size - what's already there */
2507 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2508 &att_num, &att_size);
2509 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2512 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2514 const gchar *uri = (const gchar *) uri_node->data;
2517 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2519 if (total_size > allowed_size) {
2520 g_debug ("%s: total size: %u",
2521 __FUNCTION__, (unsigned int)total_size);
2524 allowed_size -= total_size;
2526 g_slist_foreach (uris, (GFunc) g_free, NULL);
2527 g_slist_free (uris);
2529 gtk_widget_destroy (GTK_WIDGET (dialog));
2533 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2535 GtkWidget *dialog = NULL;
2536 ModestMsgEditWindowPrivate *priv;
2539 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2541 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2543 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2546 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2547 GTK_FILE_CHOOSER_ACTION_OPEN);
2548 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2549 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2550 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2551 if (conf_folder && conf_folder[0] != '\0') {
2552 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2555 /* Set the default folder to documents folder */
2556 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2559 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2560 ".documents", NULL);
2562 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2563 g_free (docs_folder);
2565 g_free (conf_folder);
2566 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2567 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2568 GTK_WINDOW (dialog), GTK_WINDOW (window));
2570 /* Connect to response & show */
2571 g_signal_connect (dialog, "response",
2572 G_CALLBACK (on_attach_file_response), window);
2573 gtk_widget_show (dialog);
2578 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2580 GnomeVFSFileSize allowed_size)
2583 GnomeVFSHandle *handle = NULL;
2584 ModestMsgEditWindowPrivate *priv;
2585 GnomeVFSResult result;
2586 GnomeVFSFileSize size = 0;
2587 g_return_val_if_fail (window, 0);
2588 g_return_val_if_fail (uri, 0);
2590 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2592 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2593 if (result == GNOME_VFS_OK) {
2594 TnyMimePart *mime_part;
2596 const gchar *mime_type = NULL;
2598 gchar *escaped_filename;
2601 GnomeVFSFileInfo *info;
2602 GnomeVFSURI *vfs_uri;
2604 gnome_vfs_close (handle);
2605 vfs_uri = gnome_vfs_uri_new (uri);
2608 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2609 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2610 g_free (escaped_filename);
2611 gnome_vfs_uri_unref (vfs_uri);
2613 info = gnome_vfs_file_info_new ();
2615 if (gnome_vfs_get_file_info (uri,
2617 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2619 mime_type = gnome_vfs_file_info_get_mime_type (info);
2620 mime_part = tny_platform_factory_new_mime_part
2621 (modest_runtime_get_platform_factory ());
2623 /* try to get the attachment's size; this may fail for weird
2624 * file systems, like obex, upnp... */
2625 if (allowed_size != 0 &&
2626 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2628 if (size > allowed_size) {
2629 modest_platform_information_banner (NULL, NULL,
2630 _("mail_ib_error_attachment_size"));
2635 g_debug ("%s: could not get attachment size", __FUNCTION__);
2637 stream = create_stream_for_uri (uri);
2639 if (stream == NULL) {
2641 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2643 g_object_unref (mime_part);
2645 gnome_vfs_file_info_unref (info);
2649 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2650 g_object_unref (stream);
2652 content_id = g_strdup_printf ("%d", priv->next_cid);
2653 tny_mime_part_set_content_id (mime_part, content_id);
2654 g_free (content_id);
2657 basename = g_path_get_basename (filename);
2658 tny_mime_part_set_filename (mime_part, basename);
2661 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2662 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2664 info->size == 0, info->size);
2665 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2666 gtk_widget_show_all (priv->attachments_caption);
2667 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2669 g_object_unref (mime_part);
2670 gnome_vfs_file_info_unref (info);
2677 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2680 ModestMsgEditWindowPrivate *priv;
2683 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2684 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2686 if (att_list == NULL) {
2687 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2688 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2689 g_object_unref (att_list);
2693 g_object_ref (att_list);
2696 if (tny_list_get_length (att_list) == 0) {
2697 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2699 gboolean dialog_response;
2700 gchar *message = NULL;
2701 gchar *filename = NULL;
2703 if (tny_list_get_length (att_list) == 1) {
2705 iter = tny_list_create_iterator (att_list);
2706 part = (TnyMimePart *) tny_iterator_get_current (iter);
2707 g_object_unref (iter);
2708 if (TNY_IS_MSG (part)) {
2709 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2711 filename = tny_header_dup_subject (header);
2712 g_object_unref (header);
2714 if (filename == NULL) {
2715 filename = g_strdup (_("mail_va_no_subject"));
2718 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2720 g_object_unref (part);
2722 filename = g_strdup ("");
2724 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2725 "emev_nc_delete_attachments",
2726 tny_list_get_length (att_list)), filename);
2729 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2733 if (dialog_response != GTK_RESPONSE_OK) {
2734 g_object_unref (att_list);
2738 for (iter = tny_list_create_iterator (att_list);
2739 !tny_iterator_is_done (iter);
2740 tny_iterator_next (iter)) {
2741 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2742 const gchar *att_id;
2743 tny_list_remove (priv->attachments, (GObject *) mime_part);
2745 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2747 if (tny_list_get_length (priv->attachments) == 0)
2748 gtk_widget_hide (priv->attachments_caption);
2749 att_id = tny_mime_part_get_content_id (mime_part);
2751 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2753 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2754 g_object_unref (mime_part);
2756 g_object_unref (iter);
2759 g_object_unref (att_list);
2761 /* if the last attachment has been removed, focus the Subject: field */
2762 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2763 gtk_widget_grab_focus (priv->subject_field);
2767 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2770 ModestMsgEditWindowPrivate *priv;
2771 GdkColor *new_color;
2772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2774 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2775 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2778 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2780 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2782 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2784 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2789 font_size_clicked (GtkToolButton *button,
2790 ModestMsgEditWindow *window)
2792 ModestMsgEditWindowPrivate *priv;
2793 GtkWidget *selector, *dialog;
2795 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2797 selector = hildon_touch_selector_new ();
2798 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2799 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2801 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2802 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2803 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2805 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2809 WPTextBufferFormat format;
2811 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2813 memset (&format, 0, sizeof (format));
2814 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2816 format.cs.font_size = TRUE;
2817 format.cs.text_position = TRUE;
2818 format.cs.font = TRUE;
2819 format.font_size = new_index;
2820 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2822 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2823 GINT_TO_POINTER (new_index)))
2824 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2826 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2827 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2828 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2829 size_text, "</span>", NULL);
2831 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2835 gtk_widget_destroy (dialog);
2837 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2842 font_face_clicked (GtkToolButton *button,
2843 ModestMsgEditWindow *window)
2845 ModestMsgEditWindowPrivate *priv;
2846 GtkWidget *selector, *dialog;
2847 GtkCellRenderer *renderer;
2849 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2851 selector = hildon_touch_selector_new ();
2852 renderer = gtk_cell_renderer_text_new ();
2853 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2854 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2855 renderer, "family", 0, "text", 0, NULL);
2856 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2858 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2859 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2860 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2862 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2863 gint new_font_index;
2867 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2868 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2869 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2873 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2875 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2876 GINT_TO_POINTER(new_font_index)))
2877 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2879 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2880 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2882 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2886 gtk_tree_path_free (path);
2889 gtk_widget_destroy (dialog);
2891 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2896 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2899 ModestMsgEditWindowPrivate *priv = NULL;
2900 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2903 if (!priv->update_caption_visibility)
2906 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2908 gtk_widget_show (priv->cc_caption);
2910 gtk_widget_hide (priv->cc_caption);
2912 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2916 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2919 ModestMsgEditWindowPrivate *priv = NULL;
2920 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2922 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2923 if (!priv->update_caption_visibility)
2926 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2928 gtk_widget_show (priv->bcc_caption);
2930 gtk_widget_hide (priv->bcc_caption);
2932 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2936 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2937 ModestRecptEditor *editor)
2939 ModestMsgEditWindowPrivate *priv;
2941 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2942 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2944 /* we check for low-mem; in that case, show a warning, and don't allow
2945 * for the addressbook
2947 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2950 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2952 if (editor == NULL) {
2953 GtkWidget *view_focus, *parent;
2954 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2956 /* This code should be kept in sync with ModestRecptEditor. The
2957 textview inside the recpt editor is the one that really gets the
2958 focus. As it's inside a scrolled window, and this one inside the
2959 hbox recpt editor inherits from, we'll need to go up in the
2960 hierarchy to know if the text view is part of the recpt editor
2961 or if it's a different text entry */
2962 parent = gtk_widget_get_parent (view_focus);
2963 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2964 editor = MODEST_RECPT_EDITOR (parent);
2967 editor = MODEST_RECPT_EDITOR (priv->to_field);
2970 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2974 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2976 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2978 modest_msg_edit_window_open_addressbook (window, NULL);
2982 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2983 gboolean show_toolbar)
2985 ModestWindowPrivate *parent_priv;
2986 ModestMsgEditWindowPrivate *priv;
2988 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2989 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2990 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2992 /* We can not just use the code of
2993 modest_msg_edit_window_setup_toolbar because it has a
2994 mixture of both initialization and creation code. */
2996 gint current_format;
2997 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2998 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2999 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3000 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3002 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3005 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3010 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3011 TnyHeaderFlags priority_flags)
3013 ModestMsgEditWindowPrivate *priv;
3014 ModestWindowPrivate *parent_priv;
3016 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3018 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3019 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3021 if (priv->priority_flags != priority_flags) {
3022 GtkAction *priority_action = NULL;
3024 priv->priority_flags = priority_flags;
3026 switch (priority_flags) {
3027 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3028 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3029 MODEST_HEADER_ICON_HIGH,
3030 HILDON_ICON_SIZE_SMALL);
3031 gtk_widget_show (priv->priority_icon);
3032 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3033 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3035 case TNY_HEADER_FLAG_LOW_PRIORITY:
3036 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3037 MODEST_HEADER_ICON_LOW,
3038 HILDON_ICON_SIZE_SMALL);
3039 gtk_widget_show (priv->priority_icon);
3040 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3041 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3044 gtk_widget_hide (priv->priority_icon);
3045 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3046 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3049 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3050 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3052 gtk_widget_queue_resize (priv->subject_box);
3056 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3059 ModestMsgEditWindowPrivate *priv;
3060 ModestWindowPrivate *parent_priv;
3061 gint current_format;
3063 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3065 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3066 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3068 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3069 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3071 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3073 if (parent_priv->toolbar) {
3074 if (file_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3075 gtk_widget_hide (parent_priv->toolbar);
3077 gtk_widget_show (parent_priv->toolbar);
3081 if (current_format != file_format) {
3082 switch (file_format) {
3083 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3084 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3085 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3087 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3091 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3092 response = gtk_dialog_run (GTK_DIALOG (dialog));
3093 gtk_widget_destroy (dialog);
3094 if (response == GTK_RESPONSE_OK) {
3095 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3096 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
3098 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3099 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3104 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3105 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3106 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3111 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3114 ModestMsgEditWindowPrivate *priv;
3115 WPTextBufferFormat oldfmt, fmt;
3116 gint old_position = 0;
3120 GdkColor *color = NULL;
3121 gboolean bold, bold_set, italic, italic_set;
3122 gboolean underline, underline_set;
3123 gboolean strikethrough, strikethrough_set;
3124 gboolean position_set;
3125 gboolean font_size_set, font_set, color_set;
3128 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3129 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3131 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3132 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3133 GTK_WINDOW(dialog), GTK_WINDOW (window));
3135 /* First we get the currently selected font information */
3136 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3138 switch (oldfmt.text_position) {
3139 case TEXT_POSITION_NORMAL:
3142 case TEXT_POSITION_SUPERSCRIPT:
3150 g_object_set (G_OBJECT (dialog),
3151 "bold", oldfmt.bold != FALSE,
3152 "bold-set", !oldfmt.cs.bold,
3153 "underline", oldfmt.underline != FALSE,
3154 "underline-set", !oldfmt.cs.underline,
3155 "italic", oldfmt.italic != FALSE,
3156 "italic-set", !oldfmt.cs.italic,
3157 "strikethrough", oldfmt.strikethrough != FALSE,
3158 "strikethrough-set", !oldfmt.cs.strikethrough,
3159 "color", &oldfmt.color,
3160 "color-set", !oldfmt.cs.color,
3161 "size", wp_font_size[oldfmt.font_size],
3162 "size-set", !oldfmt.cs.font_size,
3163 "position", old_position,
3164 "position-set", !oldfmt.cs.text_position,
3165 "family", wp_get_font_name (oldfmt.font),
3166 "family-set", !oldfmt.cs.font,
3169 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3170 GTK_WINDOW (dialog), GTK_WINDOW (window));
3171 gtk_widget_show_all (dialog);
3172 priv->font_dialog = dialog;
3173 response = gtk_dialog_run (GTK_DIALOG (dialog));
3174 priv->font_dialog = NULL;
3175 if (response == GTK_RESPONSE_OK) {
3177 g_object_get( dialog,
3179 "bold-set", &bold_set,
3180 "underline", &underline,
3181 "underline-set", &underline_set,
3183 "italic-set", &italic_set,
3184 "strikethrough", &strikethrough,
3185 "strikethrough-set", &strikethrough_set,
3187 "color-set", &color_set,
3189 "size-set", &font_size_set,
3190 "family", &font_name,
3191 "family-set", &font_set,
3192 "position", &position,
3193 "position-set", &position_set,
3198 if (response == GTK_RESPONSE_OK) {
3199 memset(&fmt, 0, sizeof(fmt));
3205 fmt.italic = italic;
3206 fmt.cs.italic = TRUE;
3208 if (underline_set) {
3209 fmt.underline = underline;
3210 fmt.cs.underline = TRUE;
3212 if (strikethrough_set) {
3213 fmt.strikethrough = strikethrough;
3214 fmt.cs.strikethrough = TRUE;
3219 ? TEXT_POSITION_NORMAL
3220 : ( ( position == 1 )
3221 ? TEXT_POSITION_SUPERSCRIPT
3222 : TEXT_POSITION_SUBSCRIPT );
3223 fmt.cs.text_position = TRUE;
3224 fmt.font_size = oldfmt.font_size;
3228 fmt.cs.color = TRUE;
3231 fmt.font = wp_get_font_index(font_name,
3236 if (font_size_set) {
3237 fmt.cs.font_size = TRUE;
3238 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3240 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3241 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3243 gtk_widget_destroy (dialog);
3245 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3249 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3251 ModestMsgEditWindowPrivate *priv;
3253 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3254 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3256 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3258 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3259 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3263 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3265 ModestMsgEditWindowPrivate *priv;
3267 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3268 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3270 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3272 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3273 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3278 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3280 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3282 priv->can_undo = can_undo;
3286 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3288 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3290 priv->can_redo = can_redo;
3294 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3296 ModestMsgEditWindowPrivate *priv;
3297 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3298 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3300 return priv->can_undo;
3304 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3306 ModestMsgEditWindowPrivate *priv;
3307 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3310 return priv->can_redo;
3315 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3318 GtkTextIter match_start, match_end;
3320 if (image_id == NULL)
3323 gtk_text_buffer_get_start_iter (buffer, &iter);
3325 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3326 GSList *tags = gtk_text_iter_get_tags (&match_start);
3328 for (node = tags; node != NULL; node = g_slist_next (node)) {
3329 GtkTextTag *tag = (GtkTextTag *) node->data;
3330 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3331 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3332 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3334 offset = gtk_text_iter_get_offset (&match_start);
3335 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3336 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3340 gtk_text_iter_forward_char (&iter);
3345 message_is_empty (ModestMsgEditWindow *window)
3347 ModestMsgEditWindowPrivate *priv = NULL;
3349 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3350 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3352 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3353 * so we can ignore markup.
3355 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3358 count = gtk_text_buffer_get_char_count (buf);
3364 msg_body_focus (GtkWidget *focus,
3365 GdkEventFocus *event,
3369 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3370 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3371 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3376 recpt_field_changed (GtkTextBuffer *buffer,
3377 ModestMsgEditWindow *editor)
3379 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3380 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3384 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3386 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3387 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3391 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3394 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3395 GtkTextBuffer *buffer;
3397 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3398 gtk_text_buffer_set_modified (buffer, modified);
3399 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3400 gtk_text_buffer_set_modified (buffer, modified);
3401 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3402 gtk_text_buffer_set_modified (buffer, modified);
3403 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3407 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3409 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3410 const char *account_name;
3411 GtkTextBuffer *buffer;
3413 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3414 if (gtk_text_buffer_get_modified (buffer))
3416 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3417 if (gtk_text_buffer_get_modified (buffer))
3419 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3420 if (gtk_text_buffer_get_modified (buffer))
3422 if (gtk_text_buffer_get_modified (priv->text_buffer))
3425 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3426 if (priv->original_mailbox) {
3427 if (!account_name || strcmp (account_name, priv->original_mailbox))
3429 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3440 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3442 ModestMsgEditWindowPrivate *priv = NULL;
3443 GSList *address_list = NULL;
3445 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3446 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3448 /* check if there's no recipient added */
3449 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3450 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3451 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3452 /* no recipient contents, then select contacts */
3453 modest_msg_edit_window_open_addressbook (window, NULL);
3458 g_object_ref (window);
3459 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3460 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3461 g_object_unref (window);
3464 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3465 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3466 g_object_unref (window);
3469 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3470 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3471 g_object_unref (window);
3475 /* Add contacts to address book */
3477 modest_address_book_add_address_list (address_list);
3479 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3480 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3481 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3482 g_object_unref (window);
3489 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3490 ModestMsgEditWindow *window)
3492 modest_msg_edit_window_offer_attach_file (window);
3496 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3498 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3500 return priv->clipboard_text;
3504 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3506 ModestMsgEditWindow *window)
3508 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3509 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3512 /* It could happen that the window was already closed */
3513 if (!GTK_WIDGET_VISIBLE (window))
3516 g_object_ref (window);
3517 text = gtk_clipboard_wait_for_text (selection_clipboard);
3519 if (priv->clipboard_text != NULL) {
3520 g_free (priv->clipboard_text);
3522 priv->clipboard_text = text;
3524 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3526 g_object_unref (window);
3529 static gboolean clipboard_owner_change_idle (gpointer userdata)
3531 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3532 ModestMsgEditWindowPrivate *priv;
3534 gdk_threads_enter ();
3535 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3536 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3538 priv->clipboard_owner_idle = 0;
3539 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3540 gdk_threads_leave ();
3546 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3548 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3549 if (priv->clipboard_owner_idle == 0) {
3550 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3551 clipboard_owner_change_idle,
3552 g_object_ref (window),
3558 subject_field_move_cursor (GtkEntry *entry,
3559 GtkMovementStep step,
3564 /* It could happen that the window was already closed */
3565 if (!GTK_WIDGET_VISIBLE (window))
3568 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3572 update_window_title (ModestMsgEditWindow *window)
3574 ModestMsgEditWindowPrivate *priv = NULL;
3575 const gchar *subject;
3577 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3578 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3579 if (subject == NULL || subject[0] == '\0')
3580 subject = _("mail_va_new_email");
3582 gtk_window_set_title (GTK_WINDOW (window), subject);
3588 body_insert_text (GtkTextBuffer *buffer,
3589 GtkTextIter *location,
3592 ModestMsgEditWindow *window)
3594 GtkTextIter end_iter;
3601 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3603 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3605 offset = gtk_text_iter_get_offset (&end_iter);
3606 line = gtk_text_iter_get_line (&end_iter);
3610 while (text_offset < text + len) {
3611 if (*text_offset == '\n')
3613 if (text_lines + line >= MAX_BODY_LINES) {
3614 len = text_offset - text;
3620 utf8_len = g_utf8_strlen (text, len);
3622 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3623 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3624 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3629 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3631 /* Prevent endless recursion */
3632 result = g_strndup (text, utf8_end - text);
3633 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3634 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3635 (gpointer) result, (gpointer) (utf8_end - text),
3637 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3641 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3642 if (priv->max_chars_banner == NULL) {
3643 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3644 _CS("ckdg_ib_maximum_characters_reached"));
3645 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3651 subject_field_changed (GtkEditable *editable,
3652 ModestMsgEditWindow *window)
3654 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3655 update_window_title (window);
3656 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3657 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3658 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3661 subject_field_insert_text (GtkEditable *editable,
3663 gint new_text_length,
3665 ModestMsgEditWindow *window)
3667 GString *result = g_string_new ("");
3669 gint result_len = 0;
3670 const gchar *entry_text = NULL;
3673 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3674 old_length = g_utf8_strlen (entry_text, -1);
3676 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3677 gunichar c = g_utf8_get_char_validated (current, 8);
3678 /* Invalid unichar, stop */
3684 result = g_string_append_unichar (result, c);
3688 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3689 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3692 /* Prevent endless recursion */
3693 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3694 g_signal_emit_by_name (editable, "insert-text",
3695 (gpointer) result->str, (gpointer) result->len,
3696 (gpointer) position, (gpointer) window);
3697 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3701 if (result_len + old_length > 1000) {
3702 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3703 _CS("ckdg_ib_maximum_characters_reached"));
3705 g_string_free (result, TRUE);
3709 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3712 ModestMsgEditWindowPrivate *priv = NULL;
3714 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3715 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3717 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3720 gtk_widget_show_all (priv->find_toolbar);
3721 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3723 gtk_widget_hide_all (priv->find_toolbar);
3724 gtk_widget_grab_focus (priv->msg_body);
3729 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3731 GtkTextIter *match_start,
3732 GtkTextIter *match_end)
3734 GtkTextIter end_iter;
3735 gchar *str_casefold;
3738 gchar *range_casefold;
3741 gboolean result = FALSE;
3748 gtk_text_iter_forward_to_end (&end_iter);
3750 str_casefold = g_utf8_casefold (str, -1);
3751 str_chars_n = strlen (str);
3753 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3754 range_casefold = g_utf8_casefold (range_text, -1);
3755 range_chars_n = strlen (range_casefold);
3757 if (range_chars_n < str_chars_n) {
3758 g_free (str_casefold);
3759 g_free (range_text);
3760 g_free (range_casefold);
3764 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3765 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3766 if (!g_utf8_collate (range_subtext, str_casefold)) {
3767 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3769 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3770 match_start, match_end, NULL)) {
3771 g_debug ("Matched string with collate, but not matched in model");
3773 g_free (found_text);
3775 g_free (range_subtext);
3779 g_free (str_casefold);
3780 g_free (range_text);
3781 g_free (range_casefold);
3788 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3789 ModestMsgEditWindow *window)
3791 gchar *current_search = NULL;
3792 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3794 GtkTextIter selection_start, selection_end;
3795 GtkTextIter match_start, match_end;
3796 gboolean continue_search = FALSE;
3798 if (message_is_empty (window)) {
3799 g_free (priv->last_search);
3800 priv->last_search = NULL;
3801 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3805 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3806 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3807 g_free (current_search);
3808 g_free (priv->last_search);
3809 priv->last_search = NULL;
3810 /* Information banner about empty search */
3811 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3815 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3816 continue_search = TRUE;
3818 g_free (priv->last_search);
3819 priv->last_search = g_strdup (current_search);
3822 if (continue_search) {
3823 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3824 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3825 &match_start, &match_end);
3827 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3829 GtkTextIter buffer_start;
3830 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3831 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3832 &match_start, &match_end);
3834 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3837 /* Mark as selected the string found in search */
3839 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3840 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3841 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3843 g_free (priv->last_search);
3844 priv->last_search = NULL;
3846 g_free (current_search);
3850 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3852 ModestMsgEditWindowPrivate *priv;
3854 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3859 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3862 ModestMsgEditWindowPrivate *priv;
3864 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3869 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3870 ModestMsgEditWindow *window)
3872 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3876 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3879 ModestMsgEditWindowPrivate *priv;
3880 TnyHeader *header = NULL;
3882 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3883 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3885 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3887 if (priv->draft_msg != NULL) {
3888 g_object_unref (priv->draft_msg);
3891 if (draft != NULL) {
3892 g_object_ref (draft);
3893 header = tny_msg_get_header (draft);
3894 if (priv->msg_uid) {
3895 g_free (priv->msg_uid);
3896 priv->msg_uid = NULL;
3898 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3901 priv->draft_msg = draft;
3905 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3906 GtkTextIter *start, GtkTextIter *end,
3909 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3910 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3913 if (tag == NULL) return;
3914 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3915 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3916 replace_with_images (window, priv->images);
3921 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3924 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3926 g_return_if_fail (TNY_IS_MIME_PART (part));
3927 tny_list_prepend (priv->attachments, (GObject *) part);
3928 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3929 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3930 gtk_widget_show_all (priv->attachments_caption);
3931 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3935 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3937 ModestMsgEditWindowPrivate *priv;
3939 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3942 return priv->msg_uid;
3946 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3947 ModestMsgEditWindowWidgetType widget_type)
3949 ModestMsgEditWindowPrivate *priv;
3951 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3952 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3954 switch (widget_type) {
3955 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3956 return priv->msg_body;
3958 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3959 return priv->to_field;
3961 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3962 return priv->cc_field;
3964 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3965 return priv->bcc_field;
3967 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3968 return priv->subject_field;
3970 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3971 return priv->attachments_view;
3979 remove_tags (WPTextBuffer *buffer)
3981 GtkTextIter start, end;
3983 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3984 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3986 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3990 on_account_removed (TnyAccountStore *account_store,
3991 TnyAccount *account,
3994 /* Do nothing if it's a store account, because we use the
3995 transport to send the messages */
3996 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3997 const gchar *parent_acc = NULL;
3998 const gchar *our_acc = NULL;
4000 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4001 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4002 /* Close this window if I'm showing a message of the removed account */
4003 if (strcmp (parent_acc, our_acc) == 0)
4004 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4009 update_signature (ModestMsgEditWindow *self,
4010 const gchar *old_account,
4011 const gchar *new_account)
4013 ModestMsgEditWindowPrivate *priv;
4014 gboolean has_old_signature, has_new_signature;
4016 ModestAccountMgr *mgr;
4019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4021 gtk_text_buffer_begin_user_action (priv->text_buffer);
4023 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4024 mgr = modest_runtime_get_account_mgr ();
4028 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4029 if (has_old_signature) {
4030 GtkTextIter match_start, match_end;
4032 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4033 seems that the search has some problems
4034 with the blank space at the end */
4035 if (gtk_text_iter_forward_search (&iter, "--",
4036 GTK_TEXT_SEARCH_TEXT_ONLY,
4037 &match_start, NULL, NULL)) {
4038 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4039 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4041 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4042 &match_start, &match_end, NULL)) {
4049 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4050 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4051 if (has_new_signature) {
4052 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4054 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4055 g_free (full_signature);
4058 gtk_text_buffer_end_user_action (priv->text_buffer);
4061 static void update_branding (ModestMsgEditWindow *self,
4062 const gchar *new_account)
4064 ModestMsgEditWindowPrivate *priv;
4065 ModestAccountMgr *mgr;
4066 const GdkPixbuf *new_icon = NULL;
4067 gchar *new_label = NULL;
4068 gboolean show = FALSE;
4070 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4072 mgr = modest_runtime_get_account_mgr ();
4074 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4076 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4077 gtk_widget_show (priv->brand_icon);
4080 gtk_widget_hide (priv->brand_icon);
4083 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4084 gtk_widget_show (priv->brand_label);
4088 gtk_widget_hide (priv->brand_label);
4092 gtk_widget_show (priv->brand_container);
4094 gtk_widget_hide (priv->brand_container);
4098 from_field_changed (HildonPickerButton *button,
4099 ModestMsgEditWindow *self)
4101 ModestMsgEditWindowPrivate *priv;
4102 gchar *old_account, *new_account;
4104 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4106 old_account = priv->last_from_account;
4107 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4110 g_warning ("%s, could not get the new account", __FUNCTION__);
4114 /* If the From is the same do nothing */
4115 if (old_account && new_account && !strcmp (old_account, new_account))
4118 priv->last_from_account = new_account;
4120 update_signature (self, old_account, new_account);
4121 update_branding (self, new_account);
4125 typedef struct _MessageSettingsHelper {
4126 ModestMsgEditWindow *window;
4127 GSList *priority_group;
4128 GSList *format_group;
4129 GtkToggleButton *current_priority;
4130 GtkToggleButton *current_format;
4131 } MessageSettingsHelper;
4134 on_priority_toggle (GtkToggleButton *button,
4135 MessageSettingsHelper *helper)
4138 ModestMsgEditWindowPrivate *priv;
4140 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4141 if (gtk_toggle_button_get_active (button)) {
4143 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4144 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4145 if ((node_button != button) &&
4146 gtk_toggle_button_get_active (node_button)) {
4147 gtk_toggle_button_set_active (node_button, FALSE);
4150 helper->current_priority = button;
4152 gboolean found = FALSE;
4153 /* If no one is active, activate it again */
4154 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4155 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4156 if (gtk_toggle_button_get_active (node_button)) {
4162 gtk_toggle_button_set_active (button, TRUE);
4168 on_format_toggle (GtkToggleButton *button,
4169 MessageSettingsHelper *helper)
4172 ModestMsgEditWindowPrivate *priv;
4174 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4175 if (gtk_toggle_button_get_active (button)) {
4177 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4178 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4179 if ((node_button != button) &&
4180 gtk_toggle_button_get_active (node_button)) {
4181 gtk_toggle_button_set_active (node_button, FALSE);
4184 helper->current_format = button;
4186 gboolean found = FALSE;
4187 /* If no one is active, activate it again */
4188 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4189 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4190 if (gtk_toggle_button_get_active (node_button)) {
4196 gtk_toggle_button_set_active (button, TRUE);
4203 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4208 GtkWidget *priority_hbox;
4209 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4210 GtkWidget *captioned;
4211 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4212 GtkWidget *format_hbox;
4213 GtkWidget *html_toggle, *text_toggle;
4214 ModestMsgEditWindowPrivate *priv;
4215 MessageSettingsHelper helper = {0,};
4217 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4218 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4219 helper.window = window;
4220 helper.priority_group = NULL;
4221 helper.format_group = NULL;
4223 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4224 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4226 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4227 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4228 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4229 vbox = gtk_vbox_new (FALSE, 0);
4230 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4231 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4232 gtk_container_add (GTK_CONTAINER (align), vbox);
4233 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4234 gtk_widget_show (align);
4235 gtk_widget_show (vbox);
4237 /* Priority toggles */
4238 priority_hbox = gtk_hbox_new (TRUE, 0);
4239 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4240 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4241 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4242 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4243 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4244 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4245 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4246 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4247 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4248 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4249 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4250 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4251 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4252 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4253 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4254 gtk_widget_show_all (priority_hbox);
4255 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4256 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4257 gtk_widget_show (captioned);
4258 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4260 /* format toggles */
4261 format_hbox = gtk_hbox_new (TRUE, 0);
4262 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4263 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4264 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4265 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4266 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4267 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4268 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4269 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4270 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4271 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4272 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4273 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4274 gtk_widget_show_all (format_hbox);
4275 gtk_widget_show (format_hbox);
4276 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4279 g_object_unref (title_sizegroup);
4280 g_object_unref (value_sizegroup);
4282 /* Set current values */
4283 switch (priv->priority_flags) {
4284 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4285 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4286 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4288 case TNY_HEADER_FLAG_LOW_PRIORITY:
4289 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4290 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4293 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4294 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4298 switch (modest_msg_edit_window_get_format (window)) {
4299 case MODEST_MSG_EDIT_FORMAT_TEXT:
4300 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4301 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4303 case MODEST_MSG_EDIT_FORMAT_HTML:
4305 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4306 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4310 /* Signal connects */
4311 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4312 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4313 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4314 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4315 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4317 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4318 GTK_WINDOW (dialog), GTK_WINDOW (window));
4320 /* Save settings if the user clicked on done */
4321 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4322 TnyHeaderFlags flags;
4323 ModestMsgEditFormat old_format, new_format;
4325 /* Set priority flags */
4326 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4327 if (priv->priority_flags != flags)
4328 modest_msg_edit_window_set_priority_flags (window, flags);
4330 /* Set edit format */
4331 old_format = modest_msg_edit_window_get_format (window);
4332 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4333 if (old_format != new_format) {
4334 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4335 modest_msg_edit_window_set_file_format (window, file_format);
4339 gtk_widget_destroy (dialog);
4340 g_slist_free (helper.priority_group);
4344 on_message_settings (GtkAction *action,
4345 ModestMsgEditWindow *window)
4347 modest_msg_edit_window_show_msg_settings_dialog (window);
4351 on_cc_button_toggled (HildonCheckButton *button,
4352 ModestMsgEditWindow *window)
4354 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4356 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4357 hildon_check_button_get_active (button));
4361 on_bcc_button_toggled (HildonCheckButton *button,
4362 ModestMsgEditWindow *window)
4364 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4366 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4367 hildon_check_button_get_active (button));
4371 setup_menu (ModestMsgEditWindow *self)
4373 ModestMsgEditWindowPrivate *priv = NULL;
4375 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4377 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4379 /* Settings menu buttons */
4380 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4381 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4383 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4384 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4385 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4387 priv->cc_button = hildon_check_button_new (0);
4388 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4389 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4391 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4393 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4394 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4395 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4396 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4398 priv->bcc_button = hildon_check_button_new (0);
4399 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4400 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4402 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4404 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4405 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4406 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4407 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4409 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4410 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4411 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4412 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4413 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4415 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4416 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4417 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4418 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4419 APP_MENU_CALLBACK (on_message_settings),
4421 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4422 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4427 emit_open_addressbook (GtkButton *button,
4428 ModestRecptEditor *editor)
4430 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4434 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4435 const gchar *label, GtkWidget *control)
4437 GtkWidget *abook_button;
4440 GtkWidget *label_widget;
4442 box = gtk_hbox_new (FALSE, 0);
4444 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4445 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4447 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4448 label_widget = gtk_label_new (label);
4449 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4450 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4452 gtk_container_add (GTK_CONTAINER (align), abook_button);
4453 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4454 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4455 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4456 if (title_size_group)
4457 gtk_size_group_add_widget (title_size_group, label_widget);
4458 if (value_size_group)
4459 gtk_size_group_add_widget (value_size_group, control);
4461 g_signal_connect (G_OBJECT (abook_button), "clicked",
4462 G_CALLBACK (emit_open_addressbook), control);
4468 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4470 ModestMsgEditWindowPrivate *priv = NULL;
4472 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4474 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4475 priv->max_chars_banner = NULL;