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 gchar *quoted_names = modest_text_utils_quote_names (to);
1364 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1365 g_free (quoted_names);
1368 field_view_set = TRUE;
1370 gchar *quoted_names = modest_text_utils_quote_names (cc);
1371 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1372 g_free (quoted_names);
1373 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1374 gtk_widget_show (priv->cc_caption);
1375 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1376 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1377 gtk_widget_hide (priv->cc_caption);
1378 field_view_set = FALSE;
1380 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1382 field_view_set = TRUE;
1384 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1385 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1386 g_free (quoted_names);
1387 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1388 gtk_widget_show (priv->bcc_caption);
1389 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1390 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1391 gtk_widget_hide (priv->bcc_caption);
1392 field_view_set = FALSE;
1394 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1398 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1399 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1402 update_window_title (self);
1404 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1405 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1407 if ((body == NULL)||(body[0] == '\0')) {
1409 body = modest_text_utils_convert_to_html ("");
1412 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1413 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1416 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1419 /* Add attachments to the view */
1420 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1421 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1422 if (tny_list_get_length (priv->attachments) == 0) {
1423 gtk_widget_hide (priv->attachments_caption);
1425 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1426 gtk_widget_show_all (priv->attachments_caption);
1428 get_related_images (self, msg);
1429 update_next_cid (self, priv->attachments);
1430 update_next_cid (self, priv->images);
1431 replace_with_images (self, priv->images);
1433 if (preserve_is_rich && !is_html) {
1434 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1435 /* Get the default format required from configuration */
1436 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1437 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1440 /* Set the default focus depending on having already a To: field or not */
1441 if ((!to)||(*to == '\0')) {
1442 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1444 gtk_widget_grab_focus (priv->msg_body);
1447 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1449 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1450 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1452 modest_msg_edit_window_set_modified (self, FALSE);
1454 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1455 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1456 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1457 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1459 if (priv->msg_uid) {
1460 g_free (priv->msg_uid);
1461 priv->msg_uid = NULL;
1464 /* we should set a reference to the incoming message if it is a draft */
1465 msg_folder = tny_msg_get_folder (msg);
1467 if (modest_tny_folder_is_local_folder (msg_folder)) {
1468 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1469 if (type == TNY_FOLDER_TYPE_INVALID)
1470 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1472 if (type == TNY_FOLDER_TYPE_DRAFTS)
1473 priv->draft_msg = g_object_ref(msg);
1474 if (type == TNY_FOLDER_TYPE_OUTBOX)
1475 priv->outbox_msg = g_object_ref(msg);
1476 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1478 g_object_unref (msg_folder);
1489 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1491 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1492 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1493 GtkWidget *placeholder;
1494 GtkWidget *tool_item;
1499 GtkWidget *sizes_menu;
1500 GtkWidget *fonts_menu;
1506 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1507 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1508 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1509 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1511 /* Font color placeholder */
1512 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1513 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1516 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1517 priv->font_color_button = hildon_color_button_new ();
1518 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1519 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1520 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1521 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1522 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1523 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1524 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1525 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1527 G_CALLBACK (modest_msg_edit_window_color_button_change),
1530 /* Font size and face placeholder */
1531 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1532 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1534 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1535 priv->size_tool_button_label = gtk_label_new (NULL);
1536 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1537 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1538 size_text, "</span>", NULL);
1539 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1540 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1542 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1543 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1544 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1545 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1546 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1547 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1548 gtk_widget_set_sensitive (arrow, FALSE);
1549 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1550 sizes_menu = gtk_menu_new ();
1551 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1552 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1555 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1556 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1558 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1562 if (wp_font_size[size_index] == 12)
1563 priv->current_size_index = size_index;
1567 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1568 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1569 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1570 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1571 priv->font_size_toolitem = tool_item;
1574 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1575 priv->font_tool_button_label = gtk_label_new (NULL);
1576 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1577 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1578 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1580 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1581 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1582 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1583 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1584 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1585 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1586 gtk_widget_set_sensitive (arrow, FALSE);
1587 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1588 fonts_menu = gtk_menu_new ();
1589 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1590 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1593 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1595 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1596 0, wp_get_font_name (font_index),
1599 if (font_index == DEFAULT_FONT)
1600 priv->current_face_index = font_index;
1602 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1603 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1604 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1605 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1606 priv->font_face_toolitem = tool_item;
1608 /* Set expand and homogeneous for remaining items */
1609 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1610 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1611 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1612 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1613 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1614 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1616 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1617 will not show the tool items added to the placeholders) */
1618 gtk_widget_show_all (parent_priv->toolbar);
1620 /* Set the no show all *after* showing all items. We do not
1621 want the toolbar to be shown with a show all because it
1622 could go agains the gconf setting regarding showing or not
1623 the toolbar of the editor window */
1624 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1630 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1633 ModestWindowPrivate *parent_priv;
1634 ModestMsgEditWindowPrivate *priv;
1635 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1636 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1637 ModestWindowMgr *mgr = NULL;
1639 g_return_val_if_fail (msg, NULL);
1640 g_return_val_if_fail (account_name, NULL);
1642 mgr = modest_runtime_get_window_mgr ();
1644 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1646 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1647 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1649 /* Menubar. Update the state of some toggles */
1650 priv->from_field_protos = get_transports ();
1651 priv->original_mailbox = NULL;
1652 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1653 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1654 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1655 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1656 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1657 priv->original_mailbox = g_strdup (mailbox);
1658 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1659 /* We set the first mailbox as the active mailbox */
1660 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1661 if (priv->original_mailbox != NULL)
1662 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1663 (gpointer) priv->original_mailbox);
1665 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1666 (gpointer) account_name);
1668 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1670 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1671 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1672 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1674 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1675 hildon_touch_selector_get_current_text
1676 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1677 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1678 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1681 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1683 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1685 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1686 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1688 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1690 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1691 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1692 /* Add common dimming rules */
1693 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1694 modest_msg_edit_window_toolbar_dimming_entries,
1695 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1696 MODEST_WINDOW (obj));
1697 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1698 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1699 MODEST_WINDOW (obj));
1700 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1701 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1702 MODEST_WINDOW (obj));
1703 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1704 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1705 MODEST_WINDOW (obj));
1706 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1707 G_CALLBACK (modest_ui_dimming_rules_on_send),
1708 MODEST_WINDOW (obj));
1709 /* Insert dimming rules group for this window */
1710 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1711 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1713 /* Setup app menu */
1714 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1716 /* Checks the dimming rules */
1717 g_object_unref (toolbar_rules_group);
1718 g_object_unref (clipboard_rules_group);
1719 gtk_widget_hide (priv->priority_icon);
1720 gtk_widget_queue_resize (priv->subject_box);
1721 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1723 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1725 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1726 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1727 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1728 priv->update_caption_visibility = TRUE;
1730 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1732 /* Track account-removed signal, this window should be closed
1733 in the case we're creating a mail associated to the account
1735 priv->account_removed_handler_id =
1736 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1738 G_CALLBACK(on_account_removed),
1741 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1743 return (ModestWindow*) obj;
1747 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1749 GString **string_buffer = (GString **) user_data;
1751 *string_buffer = g_string_append (*string_buffer, buffer);
1757 * @result: A new string which should be freed with g_free().
1760 get_formatted_data (ModestMsgEditWindow *edit_window)
1762 ModestMsgEditWindowPrivate *priv;
1763 GString *string_buffer = g_string_new ("");
1765 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1767 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1769 modest_text_utils_hyperlinkify (string_buffer);
1771 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1773 return g_string_free (string_buffer, FALSE);
1778 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1781 const gchar *account_name;
1782 ModestMsgEditWindowPrivate *priv;
1783 TnyIterator *att_iter;
1784 const gchar *picker_active_id;
1786 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1788 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1790 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1791 g_return_val_if_fail (picker_active_id, NULL);
1792 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1794 /* don't free these (except from) */
1795 data = g_slice_new0 (MsgData);
1796 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1797 data->account_name = g_strdup (account_name);
1798 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1799 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1800 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1801 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1802 data->references = g_strdup (priv->references);
1803 data->in_reply_to = g_strdup (priv->in_reply_to);
1804 if (priv->draft_msg) {
1805 data->draft_msg = g_object_ref (priv->draft_msg);
1806 } else if (priv->outbox_msg) {
1807 data->draft_msg = g_object_ref (priv->outbox_msg);
1809 data->draft_msg = NULL;
1812 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1814 gtk_text_buffer_get_bounds (buf, &b, &e);
1815 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1817 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1818 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1820 data->html_body = NULL;
1822 /* deep-copy the data */
1823 att_iter = tny_list_create_iterator (priv->attachments);
1824 data->attachments = NULL;
1825 while (!tny_iterator_is_done (att_iter)) {
1826 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1827 if (!(TNY_IS_MIME_PART(part))) {
1828 g_warning ("strange data in attachment list");
1829 g_object_unref (part);
1830 tny_iterator_next (att_iter);
1833 data->attachments = g_list_append (data->attachments,
1835 tny_iterator_next (att_iter);
1837 g_object_unref (att_iter);
1839 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1840 att_iter = tny_list_create_iterator (priv->images);
1841 data->images = NULL;
1842 while (!tny_iterator_is_done (att_iter)) {
1843 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1845 if (!(TNY_IS_MIME_PART(part))) {
1846 g_warning ("strange data in attachment list");
1847 g_object_unref (part);
1848 tny_iterator_next (att_iter);
1851 cid = tny_mime_part_get_content_id (part);
1853 gchar *image_tag_id;
1854 GtkTextTag *image_tag;
1856 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1857 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1858 g_free (image_tag_id);
1860 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1862 ((gtk_text_iter_has_tag (&iter, image_tag))||
1863 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1864 data->images = g_list_append (data->images,
1865 g_object_ref (part));
1867 g_object_unref (part);
1868 tny_iterator_next (att_iter);
1870 g_object_unref (att_iter);
1872 data->priority_flags = priv->priority_flags;
1879 unref_gobject (GObject *obj, gpointer data)
1881 if (!G_IS_OBJECT(obj))
1883 g_object_unref (obj);
1887 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1890 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1898 g_free (data->from);
1899 g_free (data->subject);
1900 g_free (data->plain_body);
1901 g_free (data->html_body);
1902 g_free (data->account_name);
1903 g_free (data->references);
1904 g_free (data->in_reply_to);
1906 if (data->draft_msg != NULL) {
1907 g_object_unref (data->draft_msg);
1908 data->draft_msg = NULL;
1911 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1912 g_list_free (data->attachments);
1913 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1914 g_list_free (data->images);
1916 g_slice_free (MsgData, data);
1920 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1922 guint64 *parts_size)
1924 ModestMsgEditWindowPrivate *priv;
1926 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1928 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1930 /* TODO: add images */
1931 *parts_size += priv->images_size;
1932 *parts_count += priv->images_count;
1937 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1940 ModestMsgEditWindowPrivate *priv = NULL;
1941 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1943 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1945 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1947 return MODEST_MSG_EDIT_FORMAT_HTML;
1949 return MODEST_MSG_EDIT_FORMAT_TEXT;
1953 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1954 ModestMsgEditFormat format)
1956 ModestMsgEditWindowPrivate *priv;
1957 ModestWindowPrivate *parent_priv;
1959 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1961 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1964 case MODEST_MSG_EDIT_FORMAT_HTML:
1965 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1966 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1968 case MODEST_MSG_EDIT_FORMAT_TEXT:
1969 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1970 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1973 g_return_if_reached ();
1977 ModestMsgEditFormatState *
1978 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1980 ModestMsgEditFormatState *format_state = NULL;
1981 ModestMsgEditWindowPrivate *priv;
1982 WPTextBufferFormat *buffer_format;
1984 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1986 buffer_format = g_new0 (WPTextBufferFormat, 1);
1987 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1989 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1991 format_state = g_new0 (ModestMsgEditFormatState, 1);
1992 format_state->bold = buffer_format->bold&0x1;
1993 format_state->italics = buffer_format->italic&0x1;
1994 format_state->bullet = buffer_format->bullet&0x1;
1995 format_state->color = buffer_format->color;
1996 format_state->font_size = buffer_format->font_size;
1997 format_state->font_family = wp_get_font_name (buffer_format->font);
1998 format_state->justification = buffer_format->justification;
1999 g_free (buffer_format);
2001 return format_state;
2006 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2007 const ModestMsgEditFormatState *format_state)
2009 ModestMsgEditWindowPrivate *priv;
2010 WPTextBufferFormat *buffer_format;
2011 WPTextBufferFormat *current_format;
2013 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2014 g_return_if_fail (format_state != NULL);
2016 buffer_format = g_new0 (WPTextBufferFormat, 1);
2017 current_format = g_new0 (WPTextBufferFormat, 1);
2019 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2020 gtk_widget_grab_focus (priv->msg_body);
2021 buffer_format->bold = (format_state->bold != FALSE);
2022 buffer_format->italic = (format_state->italics != FALSE);
2023 buffer_format->color = format_state->color;
2024 buffer_format->font_size = format_state->font_size;
2025 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2026 buffer_format->justification = format_state->justification;
2027 buffer_format->bullet = format_state->bullet;
2029 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2031 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2032 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2033 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2034 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2035 buffer_format->cs.font = (buffer_format->font != current_format->font);
2036 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2037 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2039 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2040 if (buffer_format->cs.bold) {
2041 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2042 GINT_TO_POINTER (buffer_format->bold&0x1));
2044 if (buffer_format->cs.italic) {
2045 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2046 GINT_TO_POINTER (buffer_format->italic&0x1));
2048 if (buffer_format->cs.color) {
2049 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2050 GINT_TO_POINTER (&(buffer_format->color)));
2052 if (buffer_format->cs.font_size) {
2053 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2054 GINT_TO_POINTER (buffer_format->font_size));
2056 if (buffer_format->cs.justification) {
2057 switch (buffer_format->justification) {
2058 case GTK_JUSTIFY_LEFT:
2059 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2060 GINT_TO_POINTER(TRUE));
2062 case GTK_JUSTIFY_CENTER:
2063 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2064 GINT_TO_POINTER(TRUE));
2066 case GTK_JUSTIFY_RIGHT:
2067 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2068 GINT_TO_POINTER(TRUE));
2075 if (buffer_format->cs.font) {
2076 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2077 GINT_TO_POINTER (buffer_format->font));
2079 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2080 if (buffer_format->cs.bullet) {
2081 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2082 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2084 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2086 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2088 g_free (buffer_format);
2089 g_free (current_format);
2091 /* Check dimming rules */
2092 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2093 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2097 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2099 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2101 ModestWindowPrivate *parent_priv;
2102 ModestMsgEditWindowPrivate *priv;
2104 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2105 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2107 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2108 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2109 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2110 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2112 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2113 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2114 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2117 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2119 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2120 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2122 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2123 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2125 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2126 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2129 switch (buffer_format->justification)
2131 case GTK_JUSTIFY_LEFT:
2132 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2134 case GTK_JUSTIFY_CENTER:
2135 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2137 case GTK_JUSTIFY_RIGHT:
2138 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2145 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2147 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2148 G_CALLBACK (modest_msg_edit_window_color_button_change),
2150 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2151 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2152 G_CALLBACK (modest_msg_edit_window_color_button_change),
2155 if (priv->current_size_index != buffer_format->font_size) {
2159 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2160 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2164 priv->current_size_index = buffer_format->font_size;
2166 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2167 markup = g_strconcat ("<span font_family='Sans'>",
2168 size_text, "</span>", NULL);
2170 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2174 gtk_tree_path_free (path);
2177 if (priv->current_face_index != buffer_format->font) {
2181 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2182 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2186 priv->current_face_index = buffer_format->font;
2187 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2188 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2189 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2196 g_free (buffer_format);
2200 #ifdef MODEST_HILDON_VERSION_0
2202 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2205 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2206 ModestMsgEditWindowPrivate *priv;
2207 GtkWidget *dialog = NULL;
2209 GdkColor *new_color = NULL;
2211 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2212 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2214 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2215 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2216 g_free (buffer_format);
2218 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2219 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2220 if (new_color != NULL) {
2221 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2222 (gpointer) new_color);
2225 gtk_widget_destroy (dialog);
2230 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2233 ModestMsgEditWindowPrivate *priv;
2234 GtkWidget *dialog = NULL;
2236 GdkColor *old_color = NULL;
2237 const GdkColor *new_color = NULL;
2239 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2240 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2242 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2243 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2245 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2246 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2247 if (new_color != NULL)
2248 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2250 gtk_widget_destroy (dialog);
2256 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2259 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2260 ModestMsgEditWindowPrivate *priv;
2261 GtkWidget *dialog = NULL;
2263 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2264 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2266 dialog = hildon_color_chooser_new ();
2267 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2268 g_free (buffer_format);
2270 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2272 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2273 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2276 gtk_widget_destroy (dialog);
2281 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2284 ModestMsgEditWindowPrivate *priv;
2285 GtkWidget *dialog = NULL;
2286 GdkColor *old_color = NULL;
2288 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2289 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2291 dialog = hildon_color_chooser_new ();
2292 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2294 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2296 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2297 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2299 gtk_widget_destroy (dialog);
2302 #endif /*!MODEST_HILDON_VERSION_0*/
2307 create_stream_for_uri (const gchar* uri)
2312 TnyStream *result = NULL;
2314 GnomeVFSHandle *handle = NULL;
2315 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2316 if (test == GNOME_VFS_OK) {
2317 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2318 /* Streams over OBEX (Bluetooth) are not seekable but
2319 * we expect them to be (we might need to read them
2320 * several times). So if this is a Bluetooth URI just
2321 * read the whole file into memory (this is not a fast
2322 * protocol so we can assume that these files are not
2323 * going to be very big) */
2324 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2325 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2326 TnyStream *memstream = tny_camel_mem_stream_new ();
2327 tny_stream_write_to_stream (vfssstream, memstream);
2328 g_object_unref (vfssstream);
2331 result = vfssstream;
2339 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2342 ModestMsgEditWindowPrivate *priv;
2343 GtkWidget *dialog = NULL;
2345 GSList *uris = NULL;
2346 GSList *uri_node = NULL;
2348 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2350 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2351 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2352 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2354 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2356 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2357 GTK_WINDOW (dialog), GTK_WINDOW (window));
2359 response = gtk_dialog_run (GTK_DIALOG (dialog));
2361 case GTK_RESPONSE_OK:
2363 gchar *current_folder;
2364 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2365 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2366 if (current_folder && current_folder != '\0') {
2368 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2369 current_folder, &err);
2371 g_debug ("Error storing latest used folder: %s", err->message);
2375 g_free (current_folder);
2381 gtk_widget_destroy (dialog);
2383 g_object_ref (window);
2384 /* The operation could take some time so allow the dialog to be closed */
2385 while (gtk_events_pending ())
2386 gtk_main_iteration ();
2388 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2390 GnomeVFSHandle *handle = NULL;
2391 GnomeVFSResult result;
2392 GtkTextIter position;
2393 GtkTextMark *insert_mark;
2395 uri = (const gchar *) uri_node->data;
2396 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2397 if (result == GNOME_VFS_OK) {
2399 GnomeVFSFileInfo *info;
2400 gchar *filename, *basename, *escaped_filename;
2401 TnyMimePart *mime_part;
2403 const gchar *mime_type = NULL;
2404 GnomeVFSURI *vfs_uri;
2405 guint64 stream_size;
2407 gnome_vfs_close (handle);
2408 vfs_uri = gnome_vfs_uri_new (uri);
2410 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2411 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2412 g_free (escaped_filename);
2413 gnome_vfs_uri_unref (vfs_uri);
2414 info = gnome_vfs_file_info_new ();
2416 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2417 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2419 mime_type = gnome_vfs_file_info_get_mime_type (info);
2421 mime_part = tny_platform_factory_new_mime_part
2422 (modest_runtime_get_platform_factory ());
2424 TnyStream *stream = create_stream_for_uri (uri);
2426 if (stream == NULL) {
2428 modest_platform_information_banner (NULL, NULL,
2429 _FM("sfil_ib_opening_not_allowed"));
2431 g_object_unref (mime_part);
2432 gnome_vfs_file_info_unref (info);
2436 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2438 content_id = g_strdup_printf ("%d", priv->next_cid);
2439 tny_mime_part_set_content_id (mime_part, content_id);
2440 g_free (content_id);
2443 basename = g_path_get_basename (filename);
2444 tny_mime_part_set_filename (mime_part, basename);
2447 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2449 if (pixbuf != NULL) {
2450 priv->images_size += stream_size;
2451 priv->images_count ++;
2452 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2453 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2454 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2455 tny_mime_part_get_content_id (mime_part), pixbuf);
2456 g_object_unref (pixbuf);
2458 tny_list_prepend (priv->images, (GObject *) mime_part);
2459 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2461 modest_platform_information_banner (NULL, NULL,
2462 _("mail_ib_file_operation_failed"));
2466 g_object_unref (mime_part);
2467 gnome_vfs_file_info_unref (info);
2471 g_object_unref (window);
2475 on_attach_file_response (GtkDialog *dialog,
2479 GSList *uris = NULL;
2481 GnomeVFSFileSize total_size, allowed_size;
2482 ModestMsgEditWindow *window;
2483 ModestMsgEditWindowPrivate *priv;
2488 case GTK_RESPONSE_OK:
2490 gchar *current_folder;
2492 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2493 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2494 if (current_folder && current_folder != '\0') {
2496 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2497 current_folder, &err);
2499 g_debug ("Error storing latest used folder: %s", err->message);
2503 g_free (current_folder);
2510 window = MODEST_MSG_EDIT_WINDOW (user_data);
2511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2513 /* allowed size is the maximum size - what's already there */
2514 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2515 &att_num, &att_size);
2516 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2519 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2521 const gchar *uri = (const gchar *) uri_node->data;
2524 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2526 if (total_size > allowed_size) {
2527 g_debug ("%s: total size: %u",
2528 __FUNCTION__, (unsigned int)total_size);
2531 allowed_size -= total_size;
2533 g_slist_foreach (uris, (GFunc) g_free, NULL);
2534 g_slist_free (uris);
2536 gtk_widget_destroy (GTK_WIDGET (dialog));
2540 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2542 GtkWidget *dialog = NULL;
2543 ModestMsgEditWindowPrivate *priv;
2546 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2548 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2550 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2553 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2554 GTK_FILE_CHOOSER_ACTION_OPEN);
2555 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2556 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2557 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2558 if (conf_folder && conf_folder[0] != '\0') {
2559 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2562 /* Set the default folder to documents folder */
2563 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2566 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2567 ".documents", NULL);
2569 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2570 g_free (docs_folder);
2572 g_free (conf_folder);
2573 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2574 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2575 GTK_WINDOW (dialog), GTK_WINDOW (window));
2577 /* Connect to response & show */
2578 g_signal_connect (dialog, "response",
2579 G_CALLBACK (on_attach_file_response), window);
2580 gtk_widget_show (dialog);
2585 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2587 GnomeVFSFileSize allowed_size)
2590 GnomeVFSHandle *handle = NULL;
2591 ModestMsgEditWindowPrivate *priv;
2592 GnomeVFSResult result;
2593 GnomeVFSFileSize size = 0;
2594 g_return_val_if_fail (window, 0);
2595 g_return_val_if_fail (uri, 0);
2597 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2599 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2600 if (result == GNOME_VFS_OK) {
2601 TnyMimePart *mime_part;
2603 const gchar *mime_type = NULL;
2605 gchar *escaped_filename;
2608 GnomeVFSFileInfo *info;
2609 GnomeVFSURI *vfs_uri;
2611 gnome_vfs_close (handle);
2612 vfs_uri = gnome_vfs_uri_new (uri);
2615 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2616 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2617 g_free (escaped_filename);
2618 gnome_vfs_uri_unref (vfs_uri);
2620 info = gnome_vfs_file_info_new ();
2622 if (gnome_vfs_get_file_info (uri,
2624 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2626 mime_type = gnome_vfs_file_info_get_mime_type (info);
2627 mime_part = tny_platform_factory_new_mime_part
2628 (modest_runtime_get_platform_factory ());
2630 /* try to get the attachment's size; this may fail for weird
2631 * file systems, like obex, upnp... */
2632 if (allowed_size != 0 &&
2633 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2635 if (size > allowed_size) {
2636 modest_platform_information_banner (NULL, NULL,
2637 _("mail_ib_error_attachment_size"));
2642 g_debug ("%s: could not get attachment size", __FUNCTION__);
2644 stream = create_stream_for_uri (uri);
2646 if (stream == NULL) {
2648 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2650 g_object_unref (mime_part);
2652 gnome_vfs_file_info_unref (info);
2656 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2657 g_object_unref (stream);
2659 content_id = g_strdup_printf ("%d", priv->next_cid);
2660 tny_mime_part_set_content_id (mime_part, content_id);
2661 g_free (content_id);
2664 basename = g_path_get_basename (filename);
2665 tny_mime_part_set_filename (mime_part, basename);
2668 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2669 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2671 info->size == 0, info->size);
2672 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2673 gtk_widget_show_all (priv->attachments_caption);
2674 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2676 g_object_unref (mime_part);
2677 gnome_vfs_file_info_unref (info);
2684 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2687 ModestMsgEditWindowPrivate *priv;
2690 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2691 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2693 if (att_list == NULL) {
2694 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2695 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2696 g_object_unref (att_list);
2700 g_object_ref (att_list);
2703 if (tny_list_get_length (att_list) == 0) {
2704 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2706 gboolean dialog_response;
2707 gchar *message = NULL;
2708 gchar *filename = NULL;
2710 if (tny_list_get_length (att_list) == 1) {
2712 iter = tny_list_create_iterator (att_list);
2713 part = (TnyMimePart *) tny_iterator_get_current (iter);
2714 g_object_unref (iter);
2715 if (TNY_IS_MSG (part)) {
2716 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2718 filename = tny_header_dup_subject (header);
2719 g_object_unref (header);
2721 if (filename == NULL) {
2722 filename = g_strdup (_("mail_va_no_subject"));
2725 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2727 g_object_unref (part);
2729 filename = g_strdup ("");
2731 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2732 "emev_nc_delete_attachments",
2733 tny_list_get_length (att_list)), filename);
2736 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2740 if (dialog_response != GTK_RESPONSE_OK) {
2741 g_object_unref (att_list);
2745 for (iter = tny_list_create_iterator (att_list);
2746 !tny_iterator_is_done (iter);
2747 tny_iterator_next (iter)) {
2748 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2749 const gchar *att_id;
2750 tny_list_remove (priv->attachments, (GObject *) mime_part);
2752 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2754 if (tny_list_get_length (priv->attachments) == 0)
2755 gtk_widget_hide (priv->attachments_caption);
2756 att_id = tny_mime_part_get_content_id (mime_part);
2758 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2760 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2761 g_object_unref (mime_part);
2763 g_object_unref (iter);
2766 g_object_unref (att_list);
2768 /* if the last attachment has been removed, focus the Subject: field */
2769 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2770 gtk_widget_grab_focus (priv->subject_field);
2774 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2777 ModestMsgEditWindowPrivate *priv;
2778 GdkColor *new_color;
2779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2781 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2782 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2785 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2787 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2789 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2791 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2796 font_size_clicked (GtkToolButton *button,
2797 ModestMsgEditWindow *window)
2799 ModestMsgEditWindowPrivate *priv;
2800 GtkWidget *selector, *dialog;
2802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2804 selector = hildon_touch_selector_new ();
2805 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2806 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2808 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2809 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2810 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2812 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2816 WPTextBufferFormat format;
2818 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2820 memset (&format, 0, sizeof (format));
2821 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2823 format.cs.font_size = TRUE;
2824 format.cs.text_position = TRUE;
2825 format.cs.font = TRUE;
2826 format.font_size = new_index;
2827 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2829 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2830 GINT_TO_POINTER (new_index)))
2831 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2833 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2834 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2835 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2836 size_text, "</span>", NULL);
2838 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2842 gtk_widget_destroy (dialog);
2844 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2849 font_face_clicked (GtkToolButton *button,
2850 ModestMsgEditWindow *window)
2852 ModestMsgEditWindowPrivate *priv;
2853 GtkWidget *selector, *dialog;
2854 GtkCellRenderer *renderer;
2856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2858 selector = hildon_touch_selector_new ();
2859 renderer = gtk_cell_renderer_text_new ();
2860 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2861 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2862 renderer, "family", 0, "text", 0, NULL);
2863 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2865 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2866 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2867 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2869 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2870 gint new_font_index;
2874 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2875 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2876 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2880 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2882 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2883 GINT_TO_POINTER(new_font_index)))
2884 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2886 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2887 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2889 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2893 gtk_tree_path_free (path);
2896 gtk_widget_destroy (dialog);
2898 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2903 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2906 ModestMsgEditWindowPrivate *priv = NULL;
2907 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2909 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2910 if (!priv->update_caption_visibility)
2913 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2915 gtk_widget_show (priv->cc_caption);
2917 gtk_widget_hide (priv->cc_caption);
2919 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2923 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2926 ModestMsgEditWindowPrivate *priv = NULL;
2927 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2929 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2930 if (!priv->update_caption_visibility)
2933 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2935 gtk_widget_show (priv->bcc_caption);
2937 gtk_widget_hide (priv->bcc_caption);
2939 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2943 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2944 ModestRecptEditor *editor)
2946 ModestMsgEditWindowPrivate *priv;
2948 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2949 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2951 /* we check for low-mem; in that case, show a warning, and don't allow
2952 * for the addressbook
2954 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959 if (editor == NULL) {
2960 GtkWidget *view_focus, *parent;
2961 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2963 /* This code should be kept in sync with ModestRecptEditor. The
2964 textview inside the recpt editor is the one that really gets the
2965 focus. As it's inside a scrolled window, and this one inside the
2966 hbox recpt editor inherits from, we'll need to go up in the
2967 hierarchy to know if the text view is part of the recpt editor
2968 or if it's a different text entry */
2969 parent = gtk_widget_get_parent (view_focus);
2970 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2971 editor = MODEST_RECPT_EDITOR (parent);
2974 editor = MODEST_RECPT_EDITOR (priv->to_field);
2977 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2981 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2983 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2985 modest_msg_edit_window_open_addressbook (window, NULL);
2989 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2990 gboolean show_toolbar)
2992 ModestWindowPrivate *parent_priv;
2993 ModestMsgEditWindowPrivate *priv;
2995 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2996 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2997 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2999 /* We can not just use the code of
3000 modest_msg_edit_window_setup_toolbar because it has a
3001 mixture of both initialization and creation code. */
3003 gint current_format;
3004 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3005 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3006 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3007 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3009 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3012 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3017 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3018 TnyHeaderFlags priority_flags)
3020 ModestMsgEditWindowPrivate *priv;
3021 ModestWindowPrivate *parent_priv;
3023 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3025 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3026 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3028 if (priv->priority_flags != priority_flags) {
3029 GtkAction *priority_action = NULL;
3031 priv->priority_flags = priority_flags;
3033 switch (priority_flags) {
3034 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3035 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3036 MODEST_HEADER_ICON_HIGH,
3037 HILDON_ICON_SIZE_SMALL);
3038 gtk_widget_show (priv->priority_icon);
3039 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3040 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3042 case TNY_HEADER_FLAG_LOW_PRIORITY:
3043 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3044 MODEST_HEADER_ICON_LOW,
3045 HILDON_ICON_SIZE_SMALL);
3046 gtk_widget_show (priv->priority_icon);
3047 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3048 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3051 gtk_widget_hide (priv->priority_icon);
3052 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3053 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3056 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3057 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3059 gtk_widget_queue_resize (priv->subject_box);
3063 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3066 ModestMsgEditWindowPrivate *priv;
3067 ModestWindowPrivate *parent_priv;
3068 gint current_format;
3070 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3072 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3073 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3075 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3076 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3078 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3080 if (current_format != file_format) {
3081 switch (file_format) {
3082 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3083 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3084 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3085 if (parent_priv->toolbar)
3086 gtk_widget_show (parent_priv->toolbar);
3088 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3092 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3093 response = gtk_dialog_run (GTK_DIALOG (dialog));
3094 gtk_widget_destroy (dialog);
3095 if (response == GTK_RESPONSE_OK) {
3096 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3097 if (parent_priv->toolbar)
3098 gtk_widget_hide (parent_priv->toolbar);
3100 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3101 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3106 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3107 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3108 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3113 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3116 ModestMsgEditWindowPrivate *priv;
3117 WPTextBufferFormat oldfmt, fmt;
3118 gint old_position = 0;
3122 GdkColor *color = NULL;
3123 gboolean bold, bold_set, italic, italic_set;
3124 gboolean underline, underline_set;
3125 gboolean strikethrough, strikethrough_set;
3126 gboolean position_set;
3127 gboolean font_size_set, font_set, color_set;
3130 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3131 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3133 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3134 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3135 GTK_WINDOW(dialog), GTK_WINDOW (window));
3137 /* First we get the currently selected font information */
3138 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3140 switch (oldfmt.text_position) {
3141 case TEXT_POSITION_NORMAL:
3144 case TEXT_POSITION_SUPERSCRIPT:
3152 g_object_set (G_OBJECT (dialog),
3153 "bold", oldfmt.bold != FALSE,
3154 "bold-set", !oldfmt.cs.bold,
3155 "underline", oldfmt.underline != FALSE,
3156 "underline-set", !oldfmt.cs.underline,
3157 "italic", oldfmt.italic != FALSE,
3158 "italic-set", !oldfmt.cs.italic,
3159 "strikethrough", oldfmt.strikethrough != FALSE,
3160 "strikethrough-set", !oldfmt.cs.strikethrough,
3161 "color", &oldfmt.color,
3162 "color-set", !oldfmt.cs.color,
3163 "size", wp_font_size[oldfmt.font_size],
3164 "size-set", !oldfmt.cs.font_size,
3165 "position", old_position,
3166 "position-set", !oldfmt.cs.text_position,
3167 "family", wp_get_font_name (oldfmt.font),
3168 "family-set", !oldfmt.cs.font,
3171 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3172 GTK_WINDOW (dialog), GTK_WINDOW (window));
3173 gtk_widget_show_all (dialog);
3174 priv->font_dialog = dialog;
3175 response = gtk_dialog_run (GTK_DIALOG (dialog));
3176 priv->font_dialog = NULL;
3177 if (response == GTK_RESPONSE_OK) {
3179 g_object_get( dialog,
3181 "bold-set", &bold_set,
3182 "underline", &underline,
3183 "underline-set", &underline_set,
3185 "italic-set", &italic_set,
3186 "strikethrough", &strikethrough,
3187 "strikethrough-set", &strikethrough_set,
3189 "color-set", &color_set,
3191 "size-set", &font_size_set,
3192 "family", &font_name,
3193 "family-set", &font_set,
3194 "position", &position,
3195 "position-set", &position_set,
3200 if (response == GTK_RESPONSE_OK) {
3201 memset(&fmt, 0, sizeof(fmt));
3207 fmt.italic = italic;
3208 fmt.cs.italic = TRUE;
3210 if (underline_set) {
3211 fmt.underline = underline;
3212 fmt.cs.underline = TRUE;
3214 if (strikethrough_set) {
3215 fmt.strikethrough = strikethrough;
3216 fmt.cs.strikethrough = TRUE;
3221 ? TEXT_POSITION_NORMAL
3222 : ( ( position == 1 )
3223 ? TEXT_POSITION_SUPERSCRIPT
3224 : TEXT_POSITION_SUBSCRIPT );
3225 fmt.cs.text_position = TRUE;
3226 fmt.font_size = oldfmt.font_size;
3230 fmt.cs.color = TRUE;
3233 fmt.font = wp_get_font_index(font_name,
3238 if (font_size_set) {
3239 fmt.cs.font_size = TRUE;
3240 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3242 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3243 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3245 gtk_widget_destroy (dialog);
3247 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3251 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3253 ModestMsgEditWindowPrivate *priv;
3254 ModestWindowPrivate *parent_priv;
3255 gboolean was_rich_text, is_rich_text;
3257 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3258 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3259 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3261 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3263 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3265 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3267 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3269 gtk_widget_show (parent_priv->toolbar);
3271 gtk_widget_hide (parent_priv->toolbar);
3274 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3275 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3279 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3281 ModestMsgEditWindowPrivate *priv;
3283 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3284 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3286 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3288 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3289 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3294 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3296 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3298 priv->can_undo = can_undo;
3302 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3304 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3306 priv->can_redo = can_redo;
3310 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3312 ModestMsgEditWindowPrivate *priv;
3313 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3314 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3316 return priv->can_undo;
3320 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3322 ModestMsgEditWindowPrivate *priv;
3323 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3324 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3326 return priv->can_redo;
3331 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3334 GtkTextIter match_start, match_end;
3336 if (image_id == NULL)
3339 gtk_text_buffer_get_start_iter (buffer, &iter);
3341 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3342 GSList *tags = gtk_text_iter_get_tags (&match_start);
3344 for (node = tags; node != NULL; node = g_slist_next (node)) {
3345 GtkTextTag *tag = (GtkTextTag *) node->data;
3346 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3347 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3348 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3350 offset = gtk_text_iter_get_offset (&match_start);
3351 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3352 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3356 gtk_text_iter_forward_char (&iter);
3361 message_is_empty (ModestMsgEditWindow *window)
3363 ModestMsgEditWindowPrivate *priv = NULL;
3365 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3366 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3368 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3369 * so we can ignore markup.
3371 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3374 count = gtk_text_buffer_get_char_count (buf);
3380 msg_body_focus (GtkWidget *focus,
3381 GdkEventFocus *event,
3385 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3386 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3387 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3392 recpt_field_changed (GtkTextBuffer *buffer,
3393 ModestMsgEditWindow *editor)
3395 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3396 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3400 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3402 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3403 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3407 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3410 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3411 GtkTextBuffer *buffer;
3413 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3414 gtk_text_buffer_set_modified (buffer, modified);
3415 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3416 gtk_text_buffer_set_modified (buffer, modified);
3417 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3418 gtk_text_buffer_set_modified (buffer, modified);
3419 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3423 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3425 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3426 const char *account_name;
3427 GtkTextBuffer *buffer;
3429 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3430 if (gtk_text_buffer_get_modified (buffer))
3432 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3433 if (gtk_text_buffer_get_modified (buffer))
3435 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3436 if (gtk_text_buffer_get_modified (buffer))
3438 if (gtk_text_buffer_get_modified (priv->text_buffer))
3441 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3442 if (priv->original_mailbox) {
3443 if (!account_name || strcmp (account_name, priv->original_mailbox))
3445 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3456 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3458 ModestMsgEditWindowPrivate *priv = NULL;
3459 GSList *address_list = NULL;
3461 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3462 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3464 /* check if there's no recipient added */
3465 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3466 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3467 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3468 /* no recipient contents, then select contacts */
3469 modest_msg_edit_window_open_addressbook (window, NULL);
3474 g_object_ref (window);
3475 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3476 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3477 g_object_unref (window);
3480 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3481 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3482 g_object_unref (window);
3485 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3486 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3487 g_object_unref (window);
3491 /* Add contacts to address book */
3493 modest_address_book_add_address_list (address_list);
3495 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3496 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3497 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3498 g_object_unref (window);
3505 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3506 ModestMsgEditWindow *window)
3508 modest_msg_edit_window_offer_attach_file (window);
3512 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3514 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3516 return priv->clipboard_text;
3520 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3522 ModestMsgEditWindow *window)
3524 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3525 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3528 /* It could happen that the window was already closed */
3529 if (!GTK_WIDGET_VISIBLE (window))
3532 g_object_ref (window);
3533 text = gtk_clipboard_wait_for_text (selection_clipboard);
3535 if (priv->clipboard_text != NULL) {
3536 g_free (priv->clipboard_text);
3538 priv->clipboard_text = text;
3540 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3542 g_object_unref (window);
3545 static gboolean clipboard_owner_change_idle (gpointer userdata)
3547 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3548 ModestMsgEditWindowPrivate *priv;
3550 gdk_threads_enter ();
3551 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3552 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3554 priv->clipboard_owner_idle = 0;
3555 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3556 gdk_threads_leave ();
3562 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3564 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3565 if (priv->clipboard_owner_idle == 0) {
3566 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3567 clipboard_owner_change_idle,
3568 g_object_ref (window),
3574 subject_field_move_cursor (GtkEntry *entry,
3575 GtkMovementStep step,
3580 /* It could happen that the window was already closed */
3581 if (!GTK_WIDGET_VISIBLE (window))
3584 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3588 update_window_title (ModestMsgEditWindow *window)
3590 ModestMsgEditWindowPrivate *priv = NULL;
3591 const gchar *subject;
3593 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3594 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3595 if (subject == NULL || subject[0] == '\0')
3596 subject = _("mail_va_new_email");
3598 gtk_window_set_title (GTK_WINDOW (window), subject);
3604 body_insert_text (GtkTextBuffer *buffer,
3605 GtkTextIter *location,
3608 ModestMsgEditWindow *window)
3610 GtkTextIter end_iter;
3617 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3619 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3621 offset = gtk_text_iter_get_offset (&end_iter);
3622 line = gtk_text_iter_get_line (&end_iter);
3626 while (text_offset < text + len) {
3627 if (*text_offset == '\n')
3629 if (text_lines + line >= MAX_BODY_LINES) {
3630 len = text_offset - text;
3636 utf8_len = g_utf8_strlen (text, len);
3638 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3639 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3640 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3645 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3647 /* Prevent endless recursion */
3648 result = g_strndup (text, utf8_end - text);
3649 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3650 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3651 (gpointer) result, (gpointer) (utf8_end - text),
3653 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3657 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3658 if (priv->max_chars_banner == NULL) {
3659 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3660 _CS("ckdg_ib_maximum_characters_reached"));
3661 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3667 subject_field_changed (GtkEditable *editable,
3668 ModestMsgEditWindow *window)
3670 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3671 update_window_title (window);
3672 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3673 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3674 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3677 subject_field_insert_text (GtkEditable *editable,
3679 gint new_text_length,
3681 ModestMsgEditWindow *window)
3683 GString *result = g_string_new ("");
3685 gint result_len = 0;
3686 const gchar *entry_text = NULL;
3689 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3690 old_length = g_utf8_strlen (entry_text, -1);
3692 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3693 gunichar c = g_utf8_get_char_validated (current, 8);
3694 /* Invalid unichar, stop */
3700 result = g_string_append_unichar (result, c);
3704 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3705 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3708 /* Prevent endless recursion */
3709 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3710 g_signal_emit_by_name (editable, "insert-text",
3711 (gpointer) result->str, (gpointer) result->len,
3712 (gpointer) position, (gpointer) window);
3713 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3717 if (result_len + old_length > 1000) {
3718 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3719 _CS("ckdg_ib_maximum_characters_reached"));
3721 g_string_free (result, TRUE);
3725 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3728 ModestMsgEditWindowPrivate *priv = NULL;
3730 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3731 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3733 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3736 gtk_widget_show_all (priv->find_toolbar);
3737 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3739 gtk_widget_hide_all (priv->find_toolbar);
3740 gtk_widget_grab_focus (priv->msg_body);
3745 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3747 GtkTextIter *match_start,
3748 GtkTextIter *match_end)
3750 GtkTextIter end_iter;
3751 gchar *str_casefold;
3754 gchar *range_casefold;
3757 gboolean result = FALSE;
3764 gtk_text_iter_forward_to_end (&end_iter);
3766 str_casefold = g_utf8_casefold (str, -1);
3767 str_chars_n = strlen (str);
3769 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3770 range_casefold = g_utf8_casefold (range_text, -1);
3771 range_chars_n = strlen (range_casefold);
3773 if (range_chars_n < str_chars_n) {
3774 g_free (str_casefold);
3775 g_free (range_text);
3776 g_free (range_casefold);
3780 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3781 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3782 if (!g_utf8_collate (range_subtext, str_casefold)) {
3783 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3785 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3786 match_start, match_end, NULL)) {
3787 g_debug ("Matched string with collate, but not matched in model");
3789 g_free (found_text);
3791 g_free (range_subtext);
3795 g_free (str_casefold);
3796 g_free (range_text);
3797 g_free (range_casefold);
3804 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3805 ModestMsgEditWindow *window)
3807 gchar *current_search = NULL;
3808 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3810 GtkTextIter selection_start, selection_end;
3811 GtkTextIter match_start, match_end;
3812 gboolean continue_search = FALSE;
3814 if (message_is_empty (window)) {
3815 g_free (priv->last_search);
3816 priv->last_search = NULL;
3817 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3821 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3822 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3823 g_free (current_search);
3824 g_free (priv->last_search);
3825 priv->last_search = NULL;
3826 /* Information banner about empty search */
3827 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3831 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3832 continue_search = TRUE;
3834 g_free (priv->last_search);
3835 priv->last_search = g_strdup (current_search);
3838 if (continue_search) {
3839 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3840 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3841 &match_start, &match_end);
3843 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3845 GtkTextIter buffer_start;
3846 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3847 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3848 &match_start, &match_end);
3850 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3853 /* Mark as selected the string found in search */
3855 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3856 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3857 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3859 g_free (priv->last_search);
3860 priv->last_search = NULL;
3862 g_free (current_search);
3866 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3868 ModestMsgEditWindowPrivate *priv;
3870 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3875 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3878 ModestMsgEditWindowPrivate *priv;
3880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3885 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3886 ModestMsgEditWindow *window)
3888 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3892 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3895 ModestMsgEditWindowPrivate *priv;
3896 TnyHeader *header = NULL;
3898 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3899 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3901 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3903 if (priv->draft_msg != NULL) {
3904 g_object_unref (priv->draft_msg);
3907 if (draft != NULL) {
3908 g_object_ref (draft);
3909 header = tny_msg_get_header (draft);
3910 if (priv->msg_uid) {
3911 g_free (priv->msg_uid);
3912 priv->msg_uid = NULL;
3914 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3917 priv->draft_msg = draft;
3921 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3922 GtkTextIter *start, GtkTextIter *end,
3925 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3926 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3929 if (tag == NULL) return;
3930 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3931 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3932 replace_with_images (window, priv->images);
3937 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3940 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3942 g_return_if_fail (TNY_IS_MIME_PART (part));
3943 tny_list_prepend (priv->attachments, (GObject *) part);
3944 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3945 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3946 gtk_widget_show_all (priv->attachments_caption);
3947 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3951 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3953 ModestMsgEditWindowPrivate *priv;
3955 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3956 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3958 return priv->msg_uid;
3962 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3963 ModestMsgEditWindowWidgetType widget_type)
3965 ModestMsgEditWindowPrivate *priv;
3967 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3968 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3970 switch (widget_type) {
3971 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3972 return priv->msg_body;
3974 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3975 return priv->to_field;
3977 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3978 return priv->cc_field;
3980 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3981 return priv->bcc_field;
3983 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3984 return priv->subject_field;
3986 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3987 return priv->attachments_view;
3995 remove_tags (WPTextBuffer *buffer)
3997 GtkTextIter start, end;
3999 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4000 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4002 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4006 on_account_removed (TnyAccountStore *account_store,
4007 TnyAccount *account,
4010 /* Do nothing if it's a store account, because we use the
4011 transport to send the messages */
4012 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4013 const gchar *parent_acc = NULL;
4014 const gchar *our_acc = NULL;
4016 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4017 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4018 /* Close this window if I'm showing a message of the removed account */
4019 if (strcmp (parent_acc, our_acc) == 0)
4020 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4025 update_signature (ModestMsgEditWindow *self,
4026 const gchar *old_account,
4027 const gchar *new_account)
4029 ModestMsgEditWindowPrivate *priv;
4030 gboolean has_old_signature, has_new_signature;
4032 ModestAccountMgr *mgr;
4035 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4037 gtk_text_buffer_begin_user_action (priv->text_buffer);
4039 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4040 mgr = modest_runtime_get_account_mgr ();
4044 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4045 if (has_old_signature) {
4046 GtkTextIter match_start, match_end;
4048 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4049 seems that the search has some problems
4050 with the blank space at the end */
4051 if (gtk_text_iter_forward_search (&iter, "--",
4052 GTK_TEXT_SEARCH_TEXT_ONLY,
4053 &match_start, NULL, NULL)) {
4054 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4055 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4057 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4058 &match_start, &match_end, NULL)) {
4065 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4066 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4067 if (has_new_signature) {
4068 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4070 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4071 g_free (full_signature);
4074 gtk_text_buffer_end_user_action (priv->text_buffer);
4077 static void update_branding (ModestMsgEditWindow *self,
4078 const gchar *new_account)
4080 ModestMsgEditWindowPrivate *priv;
4081 ModestAccountMgr *mgr;
4082 const GdkPixbuf *new_icon = NULL;
4083 gchar *new_label = NULL;
4084 gboolean show = FALSE;
4086 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4088 mgr = modest_runtime_get_account_mgr ();
4090 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4092 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4093 gtk_widget_show (priv->brand_icon);
4096 gtk_widget_hide (priv->brand_icon);
4099 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4100 gtk_widget_show (priv->brand_label);
4104 gtk_widget_hide (priv->brand_label);
4108 gtk_widget_show (priv->brand_container);
4110 gtk_widget_hide (priv->brand_container);
4114 from_field_changed (HildonPickerButton *button,
4115 ModestMsgEditWindow *self)
4117 ModestMsgEditWindowPrivate *priv;
4118 gchar *old_account, *new_account;
4120 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4122 old_account = priv->last_from_account;
4123 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4126 g_warning ("%s, could not get the new account", __FUNCTION__);
4130 /* If the From is the same do nothing */
4131 if (old_account && new_account && !strcmp (old_account, new_account))
4134 priv->last_from_account = new_account;
4136 update_signature (self, old_account, new_account);
4137 update_branding (self, new_account);
4141 typedef struct _MessageSettingsHelper {
4142 ModestMsgEditWindow *window;
4143 GSList *priority_group;
4144 GSList *format_group;
4145 GtkToggleButton *current_priority;
4146 GtkToggleButton *current_format;
4147 } MessageSettingsHelper;
4150 on_priority_toggle (GtkToggleButton *button,
4151 MessageSettingsHelper *helper)
4154 ModestMsgEditWindowPrivate *priv;
4156 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4157 if (gtk_toggle_button_get_active (button)) {
4159 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4160 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4161 if ((node_button != button) &&
4162 gtk_toggle_button_get_active (node_button)) {
4163 gtk_toggle_button_set_active (node_button, FALSE);
4166 helper->current_priority = button;
4168 gboolean found = FALSE;
4169 /* If no one is active, activate it again */
4170 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4171 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4172 if (gtk_toggle_button_get_active (node_button)) {
4178 gtk_toggle_button_set_active (button, TRUE);
4184 on_format_toggle (GtkToggleButton *button,
4185 MessageSettingsHelper *helper)
4188 ModestMsgEditWindowPrivate *priv;
4190 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4191 if (gtk_toggle_button_get_active (button)) {
4193 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4194 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4195 if ((node_button != button) &&
4196 gtk_toggle_button_get_active (node_button)) {
4197 gtk_toggle_button_set_active (node_button, FALSE);
4200 helper->current_format = button;
4202 gboolean found = FALSE;
4203 /* If no one is active, activate it again */
4204 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4205 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4206 if (gtk_toggle_button_get_active (node_button)) {
4212 gtk_toggle_button_set_active (button, TRUE);
4219 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4224 GtkWidget *priority_hbox;
4225 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4226 GtkWidget *captioned;
4227 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4228 GtkWidget *format_hbox;
4229 GtkWidget *html_toggle, *text_toggle;
4230 ModestMsgEditWindowPrivate *priv;
4231 MessageSettingsHelper helper = {0,};
4233 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4234 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4235 helper.window = window;
4236 helper.priority_group = NULL;
4237 helper.format_group = NULL;
4239 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4240 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4242 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4243 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4244 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4245 vbox = gtk_vbox_new (FALSE, 0);
4246 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4247 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4248 gtk_container_add (GTK_CONTAINER (align), vbox);
4249 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4250 gtk_widget_show (align);
4251 gtk_widget_show (vbox);
4253 /* Priority toggles */
4254 priority_hbox = gtk_hbox_new (TRUE, 0);
4255 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4256 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4257 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4258 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4259 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4260 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4261 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4262 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4263 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4264 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4265 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4266 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4267 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4268 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4269 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4270 gtk_widget_show_all (priority_hbox);
4271 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4272 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4273 gtk_widget_show (captioned);
4274 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4276 /* format toggles */
4277 format_hbox = gtk_hbox_new (TRUE, 0);
4278 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4279 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4280 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4281 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4282 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4283 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4284 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4285 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4286 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4287 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4288 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4289 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4290 gtk_widget_show_all (format_hbox);
4291 gtk_widget_show (format_hbox);
4292 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4295 g_object_unref (title_sizegroup);
4296 g_object_unref (value_sizegroup);
4298 /* Set current values */
4299 switch (priv->priority_flags) {
4300 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4301 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4302 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4304 case TNY_HEADER_FLAG_LOW_PRIORITY:
4305 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4306 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4309 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4310 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4314 switch (modest_msg_edit_window_get_format (window)) {
4315 case MODEST_MSG_EDIT_FORMAT_TEXT:
4316 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4317 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4319 case MODEST_MSG_EDIT_FORMAT_HTML:
4321 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4322 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4326 /* Signal connects */
4327 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4328 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4329 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4330 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4331 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4333 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4334 GTK_WINDOW (dialog), GTK_WINDOW (window));
4336 /* Save settings if the user clicked on done */
4337 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4338 TnyHeaderFlags flags;
4339 ModestMsgEditFormat old_format, new_format;
4341 /* Set priority flags */
4342 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4343 if (priv->priority_flags != flags)
4344 modest_msg_edit_window_set_priority_flags (window, flags);
4346 /* Set edit format */
4347 old_format = modest_msg_edit_window_get_format (window);
4348 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4349 if (old_format != new_format) {
4350 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4351 modest_msg_edit_window_set_file_format (window, file_format);
4355 gtk_widget_destroy (dialog);
4356 g_slist_free (helper.priority_group);
4360 on_message_settings (GtkAction *action,
4361 ModestMsgEditWindow *window)
4363 modest_msg_edit_window_show_msg_settings_dialog (window);
4367 on_cc_button_toggled (HildonCheckButton *button,
4368 ModestMsgEditWindow *window)
4370 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4372 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4373 hildon_check_button_get_active (button));
4377 on_bcc_button_toggled (HildonCheckButton *button,
4378 ModestMsgEditWindow *window)
4380 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4382 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4383 hildon_check_button_get_active (button));
4387 setup_menu (ModestMsgEditWindow *self)
4389 ModestMsgEditWindowPrivate *priv = NULL;
4391 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4393 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4395 /* Settings menu buttons */
4396 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4397 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4399 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4400 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4401 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4403 priv->cc_button = hildon_check_button_new (0);
4404 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4405 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4407 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4409 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4410 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4411 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4412 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4414 priv->bcc_button = hildon_check_button_new (0);
4415 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4416 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4418 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4420 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4421 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4422 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4423 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4425 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4426 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4427 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4428 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4429 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4431 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4432 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4433 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4434 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4435 APP_MENU_CALLBACK (on_message_settings),
4437 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4438 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4443 emit_open_addressbook (GtkButton *button,
4444 ModestRecptEditor *editor)
4446 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4450 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4451 const gchar *label, GtkWidget *control)
4453 GtkWidget *abook_button;
4456 GtkWidget *label_widget;
4458 box = gtk_hbox_new (FALSE, 0);
4460 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4461 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4463 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4464 label_widget = gtk_label_new (label);
4465 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4466 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4468 gtk_container_add (GTK_CONTAINER (align), abook_button);
4469 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4470 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4471 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4472 if (title_size_group)
4473 gtk_size_group_add_widget (title_size_group, label_widget);
4474 if (value_size_group)
4475 gtk_size_group_add_widget (value_size_group, control);
4477 g_signal_connect (G_OBJECT (abook_button), "clicked",
4478 G_CALLBACK (emit_open_addressbook), control);
4484 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4486 ModestMsgEditWindowPrivate *priv = NULL;
4488 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4491 priv->max_chars_banner = NULL;