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;
3255 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3256 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3258 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3260 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3261 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3265 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3267 ModestMsgEditWindowPrivate *priv;
3269 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3270 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3272 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3274 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3275 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3280 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3282 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3284 priv->can_undo = can_undo;
3288 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3290 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3292 priv->can_redo = can_redo;
3296 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3298 ModestMsgEditWindowPrivate *priv;
3299 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3300 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3302 return priv->can_undo;
3306 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3308 ModestMsgEditWindowPrivate *priv;
3309 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3310 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3312 return priv->can_redo;
3317 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3320 GtkTextIter match_start, match_end;
3322 if (image_id == NULL)
3325 gtk_text_buffer_get_start_iter (buffer, &iter);
3327 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3328 GSList *tags = gtk_text_iter_get_tags (&match_start);
3330 for (node = tags; node != NULL; node = g_slist_next (node)) {
3331 GtkTextTag *tag = (GtkTextTag *) node->data;
3332 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3333 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3334 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3336 offset = gtk_text_iter_get_offset (&match_start);
3337 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3338 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3342 gtk_text_iter_forward_char (&iter);
3347 message_is_empty (ModestMsgEditWindow *window)
3349 ModestMsgEditWindowPrivate *priv = NULL;
3351 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3352 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3354 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3355 * so we can ignore markup.
3357 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3360 count = gtk_text_buffer_get_char_count (buf);
3366 msg_body_focus (GtkWidget *focus,
3367 GdkEventFocus *event,
3371 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3372 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3373 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3378 recpt_field_changed (GtkTextBuffer *buffer,
3379 ModestMsgEditWindow *editor)
3381 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3382 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3386 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3388 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3389 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3393 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3396 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3397 GtkTextBuffer *buffer;
3399 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3400 gtk_text_buffer_set_modified (buffer, modified);
3401 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3402 gtk_text_buffer_set_modified (buffer, modified);
3403 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3404 gtk_text_buffer_set_modified (buffer, modified);
3405 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3409 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3411 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3412 const char *account_name;
3413 GtkTextBuffer *buffer;
3415 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3416 if (gtk_text_buffer_get_modified (buffer))
3418 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3419 if (gtk_text_buffer_get_modified (buffer))
3421 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3422 if (gtk_text_buffer_get_modified (buffer))
3424 if (gtk_text_buffer_get_modified (priv->text_buffer))
3427 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3428 if (priv->original_mailbox) {
3429 if (!account_name || strcmp (account_name, priv->original_mailbox))
3431 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3442 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3444 ModestMsgEditWindowPrivate *priv = NULL;
3445 GSList *address_list = NULL;
3447 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3448 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3450 /* check if there's no recipient added */
3451 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3452 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3453 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3454 /* no recipient contents, then select contacts */
3455 modest_msg_edit_window_open_addressbook (window, NULL);
3460 g_object_ref (window);
3461 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3462 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3463 g_object_unref (window);
3466 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3467 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3468 g_object_unref (window);
3471 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3472 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3473 g_object_unref (window);
3477 /* Add contacts to address book */
3479 modest_address_book_add_address_list (address_list);
3481 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3482 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3483 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3484 g_object_unref (window);
3491 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3492 ModestMsgEditWindow *window)
3494 modest_msg_edit_window_offer_attach_file (window);
3498 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3500 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3502 return priv->clipboard_text;
3506 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3508 ModestMsgEditWindow *window)
3510 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3511 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3514 /* It could happen that the window was already closed */
3515 if (!GTK_WIDGET_VISIBLE (window))
3518 g_object_ref (window);
3519 text = gtk_clipboard_wait_for_text (selection_clipboard);
3521 if (priv->clipboard_text != NULL) {
3522 g_free (priv->clipboard_text);
3524 priv->clipboard_text = text;
3526 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3528 g_object_unref (window);
3531 static gboolean clipboard_owner_change_idle (gpointer userdata)
3533 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3534 ModestMsgEditWindowPrivate *priv;
3536 gdk_threads_enter ();
3537 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3538 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3540 priv->clipboard_owner_idle = 0;
3541 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3542 gdk_threads_leave ();
3548 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3550 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3551 if (priv->clipboard_owner_idle == 0) {
3552 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3553 clipboard_owner_change_idle,
3554 g_object_ref (window),
3560 subject_field_move_cursor (GtkEntry *entry,
3561 GtkMovementStep step,
3566 /* It could happen that the window was already closed */
3567 if (!GTK_WIDGET_VISIBLE (window))
3570 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3574 update_window_title (ModestMsgEditWindow *window)
3576 ModestMsgEditWindowPrivate *priv = NULL;
3577 const gchar *subject;
3579 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3580 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3581 if (subject == NULL || subject[0] == '\0')
3582 subject = _("mail_va_new_email");
3584 gtk_window_set_title (GTK_WINDOW (window), subject);
3590 body_insert_text (GtkTextBuffer *buffer,
3591 GtkTextIter *location,
3594 ModestMsgEditWindow *window)
3596 GtkTextIter end_iter;
3603 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3605 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3607 offset = gtk_text_iter_get_offset (&end_iter);
3608 line = gtk_text_iter_get_line (&end_iter);
3612 while (text_offset < text + len) {
3613 if (*text_offset == '\n')
3615 if (text_lines + line >= MAX_BODY_LINES) {
3616 len = text_offset - text;
3622 utf8_len = g_utf8_strlen (text, len);
3624 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3625 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3626 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3631 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3633 /* Prevent endless recursion */
3634 result = g_strndup (text, utf8_end - text);
3635 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3636 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3637 (gpointer) result, (gpointer) (utf8_end - text),
3639 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3643 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3644 if (priv->max_chars_banner == NULL) {
3645 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3646 _CS("ckdg_ib_maximum_characters_reached"));
3647 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3653 subject_field_changed (GtkEditable *editable,
3654 ModestMsgEditWindow *window)
3656 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3657 update_window_title (window);
3658 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3659 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3660 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3663 subject_field_insert_text (GtkEditable *editable,
3665 gint new_text_length,
3667 ModestMsgEditWindow *window)
3669 GString *result = g_string_new ("");
3671 gint result_len = 0;
3672 const gchar *entry_text = NULL;
3675 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3676 old_length = g_utf8_strlen (entry_text, -1);
3678 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3679 gunichar c = g_utf8_get_char_validated (current, 8);
3680 /* Invalid unichar, stop */
3686 result = g_string_append_unichar (result, c);
3690 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3691 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3694 /* Prevent endless recursion */
3695 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3696 g_signal_emit_by_name (editable, "insert-text",
3697 (gpointer) result->str, (gpointer) result->len,
3698 (gpointer) position, (gpointer) window);
3699 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3703 if (result_len + old_length > 1000) {
3704 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3705 _CS("ckdg_ib_maximum_characters_reached"));
3707 g_string_free (result, TRUE);
3711 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3714 ModestMsgEditWindowPrivate *priv = NULL;
3716 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3717 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3719 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3722 gtk_widget_show_all (priv->find_toolbar);
3723 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3725 gtk_widget_hide_all (priv->find_toolbar);
3726 gtk_widget_grab_focus (priv->msg_body);
3731 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3733 GtkTextIter *match_start,
3734 GtkTextIter *match_end)
3736 GtkTextIter end_iter;
3737 gchar *str_casefold;
3740 gchar *range_casefold;
3743 gboolean result = FALSE;
3750 gtk_text_iter_forward_to_end (&end_iter);
3752 str_casefold = g_utf8_casefold (str, -1);
3753 str_chars_n = strlen (str);
3755 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3756 range_casefold = g_utf8_casefold (range_text, -1);
3757 range_chars_n = strlen (range_casefold);
3759 if (range_chars_n < str_chars_n) {
3760 g_free (str_casefold);
3761 g_free (range_text);
3762 g_free (range_casefold);
3766 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3767 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3768 if (!g_utf8_collate (range_subtext, str_casefold)) {
3769 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3771 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3772 match_start, match_end, NULL)) {
3773 g_debug ("Matched string with collate, but not matched in model");
3775 g_free (found_text);
3777 g_free (range_subtext);
3781 g_free (str_casefold);
3782 g_free (range_text);
3783 g_free (range_casefold);
3790 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3791 ModestMsgEditWindow *window)
3793 gchar *current_search = NULL;
3794 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3796 GtkTextIter selection_start, selection_end;
3797 GtkTextIter match_start, match_end;
3798 gboolean continue_search = FALSE;
3800 if (message_is_empty (window)) {
3801 g_free (priv->last_search);
3802 priv->last_search = NULL;
3803 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3807 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3808 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3809 g_free (current_search);
3810 g_free (priv->last_search);
3811 priv->last_search = NULL;
3812 /* Information banner about empty search */
3813 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3817 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3818 continue_search = TRUE;
3820 g_free (priv->last_search);
3821 priv->last_search = g_strdup (current_search);
3824 if (continue_search) {
3825 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3826 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3827 &match_start, &match_end);
3829 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3831 GtkTextIter buffer_start;
3832 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3833 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3834 &match_start, &match_end);
3836 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3839 /* Mark as selected the string found in search */
3841 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3842 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3843 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3845 g_free (priv->last_search);
3846 priv->last_search = NULL;
3848 g_free (current_search);
3852 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3854 ModestMsgEditWindowPrivate *priv;
3856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3861 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3864 ModestMsgEditWindowPrivate *priv;
3866 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3871 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3872 ModestMsgEditWindow *window)
3874 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3878 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3881 ModestMsgEditWindowPrivate *priv;
3882 TnyHeader *header = NULL;
3884 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3885 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3887 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3889 if (priv->draft_msg != NULL) {
3890 g_object_unref (priv->draft_msg);
3893 if (draft != NULL) {
3894 g_object_ref (draft);
3895 header = tny_msg_get_header (draft);
3896 if (priv->msg_uid) {
3897 g_free (priv->msg_uid);
3898 priv->msg_uid = NULL;
3900 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3903 priv->draft_msg = draft;
3907 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3908 GtkTextIter *start, GtkTextIter *end,
3911 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3912 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3915 if (tag == NULL) return;
3916 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3917 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3918 replace_with_images (window, priv->images);
3923 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3926 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3928 g_return_if_fail (TNY_IS_MIME_PART (part));
3929 tny_list_prepend (priv->attachments, (GObject *) part);
3930 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3931 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3932 gtk_widget_show_all (priv->attachments_caption);
3933 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3937 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3939 ModestMsgEditWindowPrivate *priv;
3941 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3942 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3944 return priv->msg_uid;
3948 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3949 ModestMsgEditWindowWidgetType widget_type)
3951 ModestMsgEditWindowPrivate *priv;
3953 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3954 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3956 switch (widget_type) {
3957 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3958 return priv->msg_body;
3960 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3961 return priv->to_field;
3963 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3964 return priv->cc_field;
3966 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3967 return priv->bcc_field;
3969 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3970 return priv->subject_field;
3972 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3973 return priv->attachments_view;
3981 remove_tags (WPTextBuffer *buffer)
3983 GtkTextIter start, end;
3985 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3986 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3988 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3992 on_account_removed (TnyAccountStore *account_store,
3993 TnyAccount *account,
3996 /* Do nothing if it's a store account, because we use the
3997 transport to send the messages */
3998 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3999 const gchar *parent_acc = NULL;
4000 const gchar *our_acc = NULL;
4002 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4003 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4004 /* Close this window if I'm showing a message of the removed account */
4005 if (strcmp (parent_acc, our_acc) == 0)
4006 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4011 update_signature (ModestMsgEditWindow *self,
4012 const gchar *old_account,
4013 const gchar *new_account)
4015 ModestMsgEditWindowPrivate *priv;
4016 gboolean has_old_signature, has_new_signature;
4018 ModestAccountMgr *mgr;
4021 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4023 gtk_text_buffer_begin_user_action (priv->text_buffer);
4025 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4026 mgr = modest_runtime_get_account_mgr ();
4030 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4031 if (has_old_signature) {
4032 GtkTextIter match_start, match_end;
4034 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4035 seems that the search has some problems
4036 with the blank space at the end */
4037 if (gtk_text_iter_forward_search (&iter, "--",
4038 GTK_TEXT_SEARCH_TEXT_ONLY,
4039 &match_start, NULL, NULL)) {
4040 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4041 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4043 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4044 &match_start, &match_end, NULL)) {
4051 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4052 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4053 if (has_new_signature) {
4054 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4056 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4057 g_free (full_signature);
4060 gtk_text_buffer_end_user_action (priv->text_buffer);
4063 static void update_branding (ModestMsgEditWindow *self,
4064 const gchar *new_account)
4066 ModestMsgEditWindowPrivate *priv;
4067 ModestAccountMgr *mgr;
4068 const GdkPixbuf *new_icon = NULL;
4069 gchar *new_label = NULL;
4070 gboolean show = FALSE;
4072 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4074 mgr = modest_runtime_get_account_mgr ();
4076 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4078 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4079 gtk_widget_show (priv->brand_icon);
4082 gtk_widget_hide (priv->brand_icon);
4085 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4086 gtk_widget_show (priv->brand_label);
4090 gtk_widget_hide (priv->brand_label);
4094 gtk_widget_show (priv->brand_container);
4096 gtk_widget_hide (priv->brand_container);
4100 from_field_changed (HildonPickerButton *button,
4101 ModestMsgEditWindow *self)
4103 ModestMsgEditWindowPrivate *priv;
4104 gchar *old_account, *new_account;
4106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4108 old_account = priv->last_from_account;
4109 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4112 g_warning ("%s, could not get the new account", __FUNCTION__);
4116 /* If the From is the same do nothing */
4117 if (old_account && new_account && !strcmp (old_account, new_account))
4120 priv->last_from_account = new_account;
4122 update_signature (self, old_account, new_account);
4123 update_branding (self, new_account);
4127 typedef struct _MessageSettingsHelper {
4128 ModestMsgEditWindow *window;
4129 GSList *priority_group;
4130 GSList *format_group;
4131 GtkToggleButton *current_priority;
4132 GtkToggleButton *current_format;
4133 } MessageSettingsHelper;
4136 on_priority_toggle (GtkToggleButton *button,
4137 MessageSettingsHelper *helper)
4140 ModestMsgEditWindowPrivate *priv;
4142 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4143 if (gtk_toggle_button_get_active (button)) {
4145 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4146 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4147 if ((node_button != button) &&
4148 gtk_toggle_button_get_active (node_button)) {
4149 gtk_toggle_button_set_active (node_button, FALSE);
4152 helper->current_priority = button;
4154 gboolean found = FALSE;
4155 /* If no one is active, activate it again */
4156 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4157 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4158 if (gtk_toggle_button_get_active (node_button)) {
4164 gtk_toggle_button_set_active (button, TRUE);
4170 on_format_toggle (GtkToggleButton *button,
4171 MessageSettingsHelper *helper)
4174 ModestMsgEditWindowPrivate *priv;
4176 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4177 if (gtk_toggle_button_get_active (button)) {
4179 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4180 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4181 if ((node_button != button) &&
4182 gtk_toggle_button_get_active (node_button)) {
4183 gtk_toggle_button_set_active (node_button, FALSE);
4186 helper->current_format = button;
4188 gboolean found = FALSE;
4189 /* If no one is active, activate it again */
4190 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4191 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4192 if (gtk_toggle_button_get_active (node_button)) {
4198 gtk_toggle_button_set_active (button, TRUE);
4205 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4210 GtkWidget *priority_hbox;
4211 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4212 GtkWidget *captioned;
4213 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4214 GtkWidget *format_hbox;
4215 GtkWidget *html_toggle, *text_toggle;
4216 ModestMsgEditWindowPrivate *priv;
4217 MessageSettingsHelper helper = {0,};
4219 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4220 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4221 helper.window = window;
4222 helper.priority_group = NULL;
4223 helper.format_group = NULL;
4225 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4226 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4228 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4229 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4230 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4231 vbox = gtk_vbox_new (FALSE, 0);
4232 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4233 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4234 gtk_container_add (GTK_CONTAINER (align), vbox);
4235 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4236 gtk_widget_show (align);
4237 gtk_widget_show (vbox);
4239 /* Priority toggles */
4240 priority_hbox = gtk_hbox_new (TRUE, 0);
4241 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4242 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4243 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4244 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4245 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4246 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4247 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4248 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4249 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4250 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4251 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4252 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4253 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4254 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4255 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4256 gtk_widget_show_all (priority_hbox);
4257 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4258 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4259 gtk_widget_show (captioned);
4260 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4262 /* format toggles */
4263 format_hbox = gtk_hbox_new (TRUE, 0);
4264 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4265 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4266 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4267 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4268 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4269 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4270 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4271 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4272 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4273 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4274 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4275 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4276 gtk_widget_show_all (format_hbox);
4277 gtk_widget_show (format_hbox);
4278 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4281 g_object_unref (title_sizegroup);
4282 g_object_unref (value_sizegroup);
4284 /* Set current values */
4285 switch (priv->priority_flags) {
4286 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4287 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4288 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4290 case TNY_HEADER_FLAG_LOW_PRIORITY:
4291 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4292 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4295 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4296 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4300 switch (modest_msg_edit_window_get_format (window)) {
4301 case MODEST_MSG_EDIT_FORMAT_TEXT:
4302 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4303 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4305 case MODEST_MSG_EDIT_FORMAT_HTML:
4307 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4308 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4312 /* Signal connects */
4313 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4314 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4315 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4316 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4317 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4319 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4320 GTK_WINDOW (dialog), GTK_WINDOW (window));
4322 /* Save settings if the user clicked on done */
4323 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4324 TnyHeaderFlags flags;
4325 ModestMsgEditFormat old_format, new_format;
4327 /* Set priority flags */
4328 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4329 if (priv->priority_flags != flags)
4330 modest_msg_edit_window_set_priority_flags (window, flags);
4332 /* Set edit format */
4333 old_format = modest_msg_edit_window_get_format (window);
4334 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4335 if (old_format != new_format) {
4336 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4337 modest_msg_edit_window_set_file_format (window, file_format);
4341 gtk_widget_destroy (dialog);
4342 g_slist_free (helper.priority_group);
4346 on_message_settings (GtkAction *action,
4347 ModestMsgEditWindow *window)
4349 modest_msg_edit_window_show_msg_settings_dialog (window);
4353 on_cc_button_toggled (HildonCheckButton *button,
4354 ModestMsgEditWindow *window)
4356 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4358 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4359 hildon_check_button_get_active (button));
4363 on_bcc_button_toggled (HildonCheckButton *button,
4364 ModestMsgEditWindow *window)
4366 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4368 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4369 hildon_check_button_get_active (button));
4373 setup_menu (ModestMsgEditWindow *self)
4375 ModestMsgEditWindowPrivate *priv = NULL;
4377 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4379 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4381 /* Settings menu buttons */
4382 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4383 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4385 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4386 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4387 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4389 priv->cc_button = hildon_check_button_new (0);
4390 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4391 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4393 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4395 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4396 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4397 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4398 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4400 priv->bcc_button = hildon_check_button_new (0);
4401 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4402 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4404 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4406 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4407 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4408 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4409 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4411 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4412 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4413 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4414 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4415 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4417 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4418 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4419 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4420 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4421 APP_MENU_CALLBACK (on_message_settings),
4423 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4424 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4429 emit_open_addressbook (GtkButton *button,
4430 ModestRecptEditor *editor)
4432 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4436 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4437 const gchar *label, GtkWidget *control)
4439 GtkWidget *abook_button;
4442 GtkWidget *label_widget;
4444 box = gtk_hbox_new (FALSE, 0);
4446 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4447 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4449 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4450 label_widget = gtk_label_new (label);
4451 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4452 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4454 gtk_container_add (GTK_CONTAINER (align), abook_button);
4455 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4456 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4457 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4458 if (title_size_group)
4459 gtk_size_group_add_widget (title_size_group, label_widget);
4460 if (value_size_group)
4461 gtk_size_group_add_widget (value_size_group, control);
4463 g_signal_connect (G_OBJECT (abook_button), "clicked",
4464 G_CALLBACK (emit_open_addressbook), control);
4470 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4472 ModestMsgEditWindowPrivate *priv = NULL;
4474 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4476 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4477 priv->max_chars_banner = NULL;