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 (current_format != file_format) {
3074 switch (file_format) {
3075 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3076 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3077 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3078 if (parent_priv->toolbar)
3079 gtk_widget_show (parent_priv->toolbar);
3081 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3085 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3086 response = gtk_dialog_run (GTK_DIALOG (dialog));
3087 gtk_widget_destroy (dialog);
3088 if (response == GTK_RESPONSE_OK) {
3089 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3090 if (parent_priv->toolbar)
3091 gtk_widget_hide (parent_priv->toolbar);
3093 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3094 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3099 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3100 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3101 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3106 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3109 ModestMsgEditWindowPrivate *priv;
3110 WPTextBufferFormat oldfmt, fmt;
3111 gint old_position = 0;
3115 GdkColor *color = NULL;
3116 gboolean bold, bold_set, italic, italic_set;
3117 gboolean underline, underline_set;
3118 gboolean strikethrough, strikethrough_set;
3119 gboolean position_set;
3120 gboolean font_size_set, font_set, color_set;
3123 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3124 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3126 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3127 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3128 GTK_WINDOW(dialog), GTK_WINDOW (window));
3130 /* First we get the currently selected font information */
3131 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3133 switch (oldfmt.text_position) {
3134 case TEXT_POSITION_NORMAL:
3137 case TEXT_POSITION_SUPERSCRIPT:
3145 g_object_set (G_OBJECT (dialog),
3146 "bold", oldfmt.bold != FALSE,
3147 "bold-set", !oldfmt.cs.bold,
3148 "underline", oldfmt.underline != FALSE,
3149 "underline-set", !oldfmt.cs.underline,
3150 "italic", oldfmt.italic != FALSE,
3151 "italic-set", !oldfmt.cs.italic,
3152 "strikethrough", oldfmt.strikethrough != FALSE,
3153 "strikethrough-set", !oldfmt.cs.strikethrough,
3154 "color", &oldfmt.color,
3155 "color-set", !oldfmt.cs.color,
3156 "size", wp_font_size[oldfmt.font_size],
3157 "size-set", !oldfmt.cs.font_size,
3158 "position", old_position,
3159 "position-set", !oldfmt.cs.text_position,
3160 "family", wp_get_font_name (oldfmt.font),
3161 "family-set", !oldfmt.cs.font,
3164 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3165 GTK_WINDOW (dialog), GTK_WINDOW (window));
3166 gtk_widget_show_all (dialog);
3167 priv->font_dialog = dialog;
3168 response = gtk_dialog_run (GTK_DIALOG (dialog));
3169 priv->font_dialog = NULL;
3170 if (response == GTK_RESPONSE_OK) {
3172 g_object_get( dialog,
3174 "bold-set", &bold_set,
3175 "underline", &underline,
3176 "underline-set", &underline_set,
3178 "italic-set", &italic_set,
3179 "strikethrough", &strikethrough,
3180 "strikethrough-set", &strikethrough_set,
3182 "color-set", &color_set,
3184 "size-set", &font_size_set,
3185 "family", &font_name,
3186 "family-set", &font_set,
3187 "position", &position,
3188 "position-set", &position_set,
3193 if (response == GTK_RESPONSE_OK) {
3194 memset(&fmt, 0, sizeof(fmt));
3200 fmt.italic = italic;
3201 fmt.cs.italic = TRUE;
3203 if (underline_set) {
3204 fmt.underline = underline;
3205 fmt.cs.underline = TRUE;
3207 if (strikethrough_set) {
3208 fmt.strikethrough = strikethrough;
3209 fmt.cs.strikethrough = TRUE;
3214 ? TEXT_POSITION_NORMAL
3215 : ( ( position == 1 )
3216 ? TEXT_POSITION_SUPERSCRIPT
3217 : TEXT_POSITION_SUBSCRIPT );
3218 fmt.cs.text_position = TRUE;
3219 fmt.font_size = oldfmt.font_size;
3223 fmt.cs.color = TRUE;
3226 fmt.font = wp_get_font_index(font_name,
3231 if (font_size_set) {
3232 fmt.cs.font_size = TRUE;
3233 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3235 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3236 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3238 gtk_widget_destroy (dialog);
3240 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3244 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3246 ModestMsgEditWindowPrivate *priv;
3248 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3249 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3251 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3253 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3254 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3258 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3260 ModestMsgEditWindowPrivate *priv;
3262 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3263 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3265 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3267 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3268 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3273 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3275 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3277 priv->can_undo = can_undo;
3281 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3283 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3285 priv->can_redo = can_redo;
3289 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3291 ModestMsgEditWindowPrivate *priv;
3292 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3293 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3295 return priv->can_undo;
3299 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3301 ModestMsgEditWindowPrivate *priv;
3302 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3303 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3305 return priv->can_redo;
3310 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3313 GtkTextIter match_start, match_end;
3315 if (image_id == NULL)
3318 gtk_text_buffer_get_start_iter (buffer, &iter);
3320 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3321 GSList *tags = gtk_text_iter_get_tags (&match_start);
3323 for (node = tags; node != NULL; node = g_slist_next (node)) {
3324 GtkTextTag *tag = (GtkTextTag *) node->data;
3325 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3326 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3327 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3329 offset = gtk_text_iter_get_offset (&match_start);
3330 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3331 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3335 gtk_text_iter_forward_char (&iter);
3340 message_is_empty (ModestMsgEditWindow *window)
3342 ModestMsgEditWindowPrivate *priv = NULL;
3344 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3345 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3347 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3348 * so we can ignore markup.
3350 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3353 count = gtk_text_buffer_get_char_count (buf);
3359 msg_body_focus (GtkWidget *focus,
3360 GdkEventFocus *event,
3364 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3365 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3366 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3371 recpt_field_changed (GtkTextBuffer *buffer,
3372 ModestMsgEditWindow *editor)
3374 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3375 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3379 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3381 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3382 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3386 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3389 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3390 GtkTextBuffer *buffer;
3392 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3393 gtk_text_buffer_set_modified (buffer, modified);
3394 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3395 gtk_text_buffer_set_modified (buffer, modified);
3396 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3397 gtk_text_buffer_set_modified (buffer, modified);
3398 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3402 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3404 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3405 const char *account_name;
3406 GtkTextBuffer *buffer;
3408 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3409 if (gtk_text_buffer_get_modified (buffer))
3411 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3412 if (gtk_text_buffer_get_modified (buffer))
3414 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3415 if (gtk_text_buffer_get_modified (buffer))
3417 if (gtk_text_buffer_get_modified (priv->text_buffer))
3420 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3421 if (priv->original_mailbox) {
3422 if (!account_name || strcmp (account_name, priv->original_mailbox))
3424 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3435 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3437 ModestMsgEditWindowPrivate *priv = NULL;
3438 GSList *address_list = NULL;
3440 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3441 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3443 /* check if there's no recipient added */
3444 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3445 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3446 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3447 /* no recipient contents, then select contacts */
3448 modest_msg_edit_window_open_addressbook (window, NULL);
3453 g_object_ref (window);
3454 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3455 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3456 g_object_unref (window);
3459 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3460 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3461 g_object_unref (window);
3464 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3465 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3466 g_object_unref (window);
3470 /* Add contacts to address book */
3472 modest_address_book_add_address_list (address_list);
3474 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3475 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3476 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3477 g_object_unref (window);
3484 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3485 ModestMsgEditWindow *window)
3487 modest_msg_edit_window_offer_attach_file (window);
3491 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3493 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3495 return priv->clipboard_text;
3499 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3501 ModestMsgEditWindow *window)
3503 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3504 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3507 /* It could happen that the window was already closed */
3508 if (!GTK_WIDGET_VISIBLE (window))
3511 g_object_ref (window);
3512 text = gtk_clipboard_wait_for_text (selection_clipboard);
3514 if (priv->clipboard_text != NULL) {
3515 g_free (priv->clipboard_text);
3517 priv->clipboard_text = text;
3519 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3521 g_object_unref (window);
3524 static gboolean clipboard_owner_change_idle (gpointer userdata)
3526 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3527 ModestMsgEditWindowPrivate *priv;
3529 gdk_threads_enter ();
3530 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3531 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3533 priv->clipboard_owner_idle = 0;
3534 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3535 gdk_threads_leave ();
3541 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3543 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3544 if (priv->clipboard_owner_idle == 0) {
3545 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3546 clipboard_owner_change_idle,
3547 g_object_ref (window),
3553 subject_field_move_cursor (GtkEntry *entry,
3554 GtkMovementStep step,
3559 /* It could happen that the window was already closed */
3560 if (!GTK_WIDGET_VISIBLE (window))
3563 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3567 update_window_title (ModestMsgEditWindow *window)
3569 ModestMsgEditWindowPrivate *priv = NULL;
3570 const gchar *subject;
3572 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3573 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3574 if (subject == NULL || subject[0] == '\0')
3575 subject = _("mail_va_new_email");
3577 gtk_window_set_title (GTK_WINDOW (window), subject);
3583 body_insert_text (GtkTextBuffer *buffer,
3584 GtkTextIter *location,
3587 ModestMsgEditWindow *window)
3589 GtkTextIter end_iter;
3596 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3598 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3600 offset = gtk_text_iter_get_offset (&end_iter);
3601 line = gtk_text_iter_get_line (&end_iter);
3605 while (text_offset < text + len) {
3606 if (*text_offset == '\n')
3608 if (text_lines + line >= MAX_BODY_LINES) {
3609 len = text_offset - text;
3615 utf8_len = g_utf8_strlen (text, len);
3617 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3618 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3619 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3624 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3626 /* Prevent endless recursion */
3627 result = g_strndup (text, utf8_end - text);
3628 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3629 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3630 (gpointer) result, (gpointer) (utf8_end - text),
3632 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3636 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3637 if (priv->max_chars_banner == NULL) {
3638 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3639 _CS("ckdg_ib_maximum_characters_reached"));
3640 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3646 subject_field_changed (GtkEditable *editable,
3647 ModestMsgEditWindow *window)
3649 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3650 update_window_title (window);
3651 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3652 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3653 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3656 subject_field_insert_text (GtkEditable *editable,
3658 gint new_text_length,
3660 ModestMsgEditWindow *window)
3662 GString *result = g_string_new ("");
3664 gint result_len = 0;
3665 const gchar *entry_text = NULL;
3668 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3669 old_length = g_utf8_strlen (entry_text, -1);
3671 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3672 gunichar c = g_utf8_get_char_validated (current, 8);
3673 /* Invalid unichar, stop */
3679 result = g_string_append_unichar (result, c);
3683 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3684 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3687 /* Prevent endless recursion */
3688 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3689 g_signal_emit_by_name (editable, "insert-text",
3690 (gpointer) result->str, (gpointer) result->len,
3691 (gpointer) position, (gpointer) window);
3692 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3696 if (result_len + old_length > 1000) {
3697 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3698 _CS("ckdg_ib_maximum_characters_reached"));
3700 g_string_free (result, TRUE);
3704 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3707 ModestMsgEditWindowPrivate *priv = NULL;
3709 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3710 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3712 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3715 gtk_widget_show_all (priv->find_toolbar);
3716 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3718 gtk_widget_hide_all (priv->find_toolbar);
3719 gtk_widget_grab_focus (priv->msg_body);
3724 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3726 GtkTextIter *match_start,
3727 GtkTextIter *match_end)
3729 GtkTextIter end_iter;
3730 gchar *str_casefold;
3733 gchar *range_casefold;
3736 gboolean result = FALSE;
3743 gtk_text_iter_forward_to_end (&end_iter);
3745 str_casefold = g_utf8_casefold (str, -1);
3746 str_chars_n = strlen (str);
3748 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3749 range_casefold = g_utf8_casefold (range_text, -1);
3750 range_chars_n = strlen (range_casefold);
3752 if (range_chars_n < str_chars_n) {
3753 g_free (str_casefold);
3754 g_free (range_text);
3755 g_free (range_casefold);
3759 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3760 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3761 if (!g_utf8_collate (range_subtext, str_casefold)) {
3762 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3764 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3765 match_start, match_end, NULL)) {
3766 g_debug ("Matched string with collate, but not matched in model");
3768 g_free (found_text);
3770 g_free (range_subtext);
3774 g_free (str_casefold);
3775 g_free (range_text);
3776 g_free (range_casefold);
3783 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3784 ModestMsgEditWindow *window)
3786 gchar *current_search = NULL;
3787 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3789 GtkTextIter selection_start, selection_end;
3790 GtkTextIter match_start, match_end;
3791 gboolean continue_search = FALSE;
3793 if (message_is_empty (window)) {
3794 g_free (priv->last_search);
3795 priv->last_search = NULL;
3796 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3800 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3801 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3802 g_free (current_search);
3803 g_free (priv->last_search);
3804 priv->last_search = NULL;
3805 /* Information banner about empty search */
3806 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3810 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3811 continue_search = TRUE;
3813 g_free (priv->last_search);
3814 priv->last_search = g_strdup (current_search);
3817 if (continue_search) {
3818 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3819 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3820 &match_start, &match_end);
3822 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3824 GtkTextIter buffer_start;
3825 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3826 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3827 &match_start, &match_end);
3829 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3832 /* Mark as selected the string found in search */
3834 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3835 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3836 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3838 g_free (priv->last_search);
3839 priv->last_search = NULL;
3841 g_free (current_search);
3845 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3847 ModestMsgEditWindowPrivate *priv;
3849 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3854 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3857 ModestMsgEditWindowPrivate *priv;
3859 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3864 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3865 ModestMsgEditWindow *window)
3867 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3871 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3874 ModestMsgEditWindowPrivate *priv;
3875 TnyHeader *header = NULL;
3877 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3878 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3882 if (priv->draft_msg != NULL) {
3883 g_object_unref (priv->draft_msg);
3886 if (draft != NULL) {
3887 g_object_ref (draft);
3888 header = tny_msg_get_header (draft);
3889 if (priv->msg_uid) {
3890 g_free (priv->msg_uid);
3891 priv->msg_uid = NULL;
3893 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3896 priv->draft_msg = draft;
3900 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3901 GtkTextIter *start, GtkTextIter *end,
3904 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3905 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3908 if (tag == NULL) return;
3909 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3910 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3911 replace_with_images (window, priv->images);
3916 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3919 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3921 g_return_if_fail (TNY_IS_MIME_PART (part));
3922 tny_list_prepend (priv->attachments, (GObject *) part);
3923 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3924 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3925 gtk_widget_show_all (priv->attachments_caption);
3926 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3930 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3932 ModestMsgEditWindowPrivate *priv;
3934 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3935 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3937 return priv->msg_uid;
3941 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3942 ModestMsgEditWindowWidgetType widget_type)
3944 ModestMsgEditWindowPrivate *priv;
3946 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3947 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3949 switch (widget_type) {
3950 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3951 return priv->msg_body;
3953 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3954 return priv->to_field;
3956 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3957 return priv->cc_field;
3959 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3960 return priv->bcc_field;
3962 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3963 return priv->subject_field;
3965 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3966 return priv->attachments_view;
3974 remove_tags (WPTextBuffer *buffer)
3976 GtkTextIter start, end;
3978 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3979 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3981 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3985 on_account_removed (TnyAccountStore *account_store,
3986 TnyAccount *account,
3989 /* Do nothing if it's a store account, because we use the
3990 transport to send the messages */
3991 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3992 const gchar *parent_acc = NULL;
3993 const gchar *our_acc = NULL;
3995 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3996 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3997 /* Close this window if I'm showing a message of the removed account */
3998 if (strcmp (parent_acc, our_acc) == 0)
3999 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4004 update_signature (ModestMsgEditWindow *self,
4005 const gchar *old_account,
4006 const gchar *new_account)
4008 ModestMsgEditWindowPrivate *priv;
4009 gboolean has_old_signature, has_new_signature;
4011 ModestAccountMgr *mgr;
4014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4016 gtk_text_buffer_begin_user_action (priv->text_buffer);
4018 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4019 mgr = modest_runtime_get_account_mgr ();
4023 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4024 if (has_old_signature) {
4025 GtkTextIter match_start, match_end;
4027 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4028 seems that the search has some problems
4029 with the blank space at the end */
4030 if (gtk_text_iter_forward_search (&iter, "--",
4031 GTK_TEXT_SEARCH_TEXT_ONLY,
4032 &match_start, NULL, NULL)) {
4033 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4034 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4036 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4037 &match_start, &match_end, NULL)) {
4044 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4045 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4046 if (has_new_signature) {
4047 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4049 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4050 g_free (full_signature);
4053 gtk_text_buffer_end_user_action (priv->text_buffer);
4056 static void update_branding (ModestMsgEditWindow *self,
4057 const gchar *new_account)
4059 ModestMsgEditWindowPrivate *priv;
4060 ModestAccountMgr *mgr;
4061 const GdkPixbuf *new_icon = NULL;
4062 gchar *new_label = NULL;
4063 gboolean show = FALSE;
4065 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4067 mgr = modest_runtime_get_account_mgr ();
4069 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4071 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4072 gtk_widget_show (priv->brand_icon);
4075 gtk_widget_hide (priv->brand_icon);
4078 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4079 gtk_widget_show (priv->brand_label);
4083 gtk_widget_hide (priv->brand_label);
4087 gtk_widget_show (priv->brand_container);
4089 gtk_widget_hide (priv->brand_container);
4093 from_field_changed (HildonPickerButton *button,
4094 ModestMsgEditWindow *self)
4096 ModestMsgEditWindowPrivate *priv;
4097 gchar *old_account, *new_account;
4099 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4101 old_account = priv->last_from_account;
4102 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4105 g_warning ("%s, could not get the new account", __FUNCTION__);
4109 /* If the From is the same do nothing */
4110 if (old_account && new_account && !strcmp (old_account, new_account))
4113 priv->last_from_account = new_account;
4115 update_signature (self, old_account, new_account);
4116 update_branding (self, new_account);
4120 typedef struct _MessageSettingsHelper {
4121 ModestMsgEditWindow *window;
4122 GSList *priority_group;
4123 GSList *format_group;
4124 GtkToggleButton *current_priority;
4125 GtkToggleButton *current_format;
4126 } MessageSettingsHelper;
4129 on_priority_toggle (GtkToggleButton *button,
4130 MessageSettingsHelper *helper)
4133 ModestMsgEditWindowPrivate *priv;
4135 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4136 if (gtk_toggle_button_get_active (button)) {
4138 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4139 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4140 if ((node_button != button) &&
4141 gtk_toggle_button_get_active (node_button)) {
4142 gtk_toggle_button_set_active (node_button, FALSE);
4145 helper->current_priority = button;
4147 gboolean found = FALSE;
4148 /* If no one is active, activate it again */
4149 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4150 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4151 if (gtk_toggle_button_get_active (node_button)) {
4157 gtk_toggle_button_set_active (button, TRUE);
4163 on_format_toggle (GtkToggleButton *button,
4164 MessageSettingsHelper *helper)
4167 ModestMsgEditWindowPrivate *priv;
4169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4170 if (gtk_toggle_button_get_active (button)) {
4172 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4173 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4174 if ((node_button != button) &&
4175 gtk_toggle_button_get_active (node_button)) {
4176 gtk_toggle_button_set_active (node_button, FALSE);
4179 helper->current_format = button;
4181 gboolean found = FALSE;
4182 /* If no one is active, activate it again */
4183 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4184 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4185 if (gtk_toggle_button_get_active (node_button)) {
4191 gtk_toggle_button_set_active (button, TRUE);
4198 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4203 GtkWidget *priority_hbox;
4204 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4205 GtkWidget *captioned;
4206 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4207 GtkWidget *format_hbox;
4208 GtkWidget *html_toggle, *text_toggle;
4209 ModestMsgEditWindowPrivate *priv;
4210 MessageSettingsHelper helper = {0,};
4212 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4213 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4214 helper.window = window;
4215 helper.priority_group = NULL;
4216 helper.format_group = NULL;
4218 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4219 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4221 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4222 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4223 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4224 vbox = gtk_vbox_new (FALSE, 0);
4225 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4226 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4227 gtk_container_add (GTK_CONTAINER (align), vbox);
4228 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4229 gtk_widget_show (align);
4230 gtk_widget_show (vbox);
4232 /* Priority toggles */
4233 priority_hbox = gtk_hbox_new (TRUE, 0);
4234 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4235 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4236 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4237 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4238 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4239 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4240 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4241 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4242 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4243 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4244 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4245 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4246 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4247 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4248 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4249 gtk_widget_show_all (priority_hbox);
4250 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4251 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4252 gtk_widget_show (captioned);
4253 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4255 /* format toggles */
4256 format_hbox = gtk_hbox_new (TRUE, 0);
4257 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4258 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4259 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4260 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4261 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4262 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4263 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4264 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4265 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4266 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4267 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4268 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4269 gtk_widget_show_all (format_hbox);
4270 gtk_widget_show (format_hbox);
4271 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4274 g_object_unref (title_sizegroup);
4275 g_object_unref (value_sizegroup);
4277 /* Set current values */
4278 switch (priv->priority_flags) {
4279 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4280 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4281 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4283 case TNY_HEADER_FLAG_LOW_PRIORITY:
4284 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4285 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4288 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4289 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4293 switch (modest_msg_edit_window_get_format (window)) {
4294 case MODEST_MSG_EDIT_FORMAT_TEXT:
4295 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4296 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4298 case MODEST_MSG_EDIT_FORMAT_HTML:
4300 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4301 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4305 /* Signal connects */
4306 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4307 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4308 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4309 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4310 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4312 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4313 GTK_WINDOW (dialog), GTK_WINDOW (window));
4315 /* Save settings if the user clicked on done */
4316 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4317 TnyHeaderFlags flags;
4318 ModestMsgEditFormat old_format, new_format;
4320 /* Set priority flags */
4321 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4322 if (priv->priority_flags != flags)
4323 modest_msg_edit_window_set_priority_flags (window, flags);
4325 /* Set edit format */
4326 old_format = modest_msg_edit_window_get_format (window);
4327 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4328 if (old_format != new_format) {
4329 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4330 modest_msg_edit_window_set_file_format (window, file_format);
4334 gtk_widget_destroy (dialog);
4335 g_slist_free (helper.priority_group);
4339 on_message_settings (GtkAction *action,
4340 ModestMsgEditWindow *window)
4342 modest_msg_edit_window_show_msg_settings_dialog (window);
4346 on_cc_button_toggled (HildonCheckButton *button,
4347 ModestMsgEditWindow *window)
4349 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4351 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4352 hildon_check_button_get_active (button));
4356 on_bcc_button_toggled (HildonCheckButton *button,
4357 ModestMsgEditWindow *window)
4359 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4361 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4362 hildon_check_button_get_active (button));
4366 setup_menu (ModestMsgEditWindow *self)
4368 ModestMsgEditWindowPrivate *priv = NULL;
4370 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4372 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4374 /* Settings menu buttons */
4375 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4376 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4378 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4379 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4380 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4382 priv->cc_button = hildon_check_button_new (0);
4383 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4384 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4386 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4388 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4389 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4390 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4391 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4393 priv->bcc_button = hildon_check_button_new (0);
4394 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4395 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4397 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4399 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4400 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4401 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4402 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4404 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4405 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4406 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4407 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4408 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4410 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4411 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4412 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4413 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4414 APP_MENU_CALLBACK (on_message_settings),
4416 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4417 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4422 emit_open_addressbook (GtkButton *button,
4423 ModestRecptEditor *editor)
4425 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4429 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4430 const gchar *label, GtkWidget *control)
4432 GtkWidget *abook_button;
4435 GtkWidget *label_widget;
4437 box = gtk_hbox_new (FALSE, 0);
4439 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4440 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4442 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4443 label_widget = gtk_label_new (label);
4444 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4445 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4447 gtk_container_add (GTK_CONTAINER (align), abook_button);
4448 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4449 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4450 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4451 if (title_size_group)
4452 gtk_size_group_add_widget (title_size_group, label_widget);
4453 if (value_size_group)
4454 gtk_size_group_add_widget (value_size_group, control);
4456 g_signal_connect (G_OBJECT (abook_button), "clicked",
4457 G_CALLBACK (emit_open_addressbook), control);
4463 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4465 ModestMsgEditWindowPrivate *priv = NULL;
4467 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4469 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4470 priv->max_chars_banner = NULL;