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 0
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_entry_set_placeholder ((HildonEntry *) priv->subject_field, _("mail_va_no_subject"));
918 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
919 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
920 gtk_box_pack_start (GTK_BOX (priv->subject_box), priv->subject_field, TRUE, TRUE, 0);
921 priv->attachments_view = modest_attachments_view_new (NULL);
922 modest_attachments_view_set_style (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
923 MODEST_ATTACHMENTS_VIEW_STYLE_NO_FOCUS);
925 priv->header_box = gtk_vbox_new (FALSE, 0);
927 to_caption = _create_addressbook_box
928 (title_size_group, value_size_group,
929 _("mail_va_to"), priv->to_field);
930 priv->cc_caption = _create_addressbook_box
931 (title_size_group, value_size_group,
932 _("mail_va_cc"), priv->cc_field);
933 priv->bcc_caption = _create_addressbook_box
934 (title_size_group, value_size_group,
935 _("mail_va_hotfix1"), priv->bcc_field);
936 subject_caption = modest_maemo_utils_create_captioned (title_size_group, value_size_group,
937 _("mail_va_subject"), FALSE, priv->subject_box);
938 priv->attachments_caption = modest_maemo_utils_create_captioned_with_size_type (NULL, NULL,
939 _("mail_va_attachment"),
941 priv->attachments_view,
942 HILDON_SIZE_AUTO_WIDTH |
943 HILDON_SIZE_AUTO_HEIGHT);
944 attachments_label = modest_maemo_utils_captioned_get_label_widget (priv->attachments_caption);
945 hildon_gtk_widget_set_theme_size (attachments_label, HILDON_SIZE_AUTO_HEIGHT);
948 priv->send_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
949 send_icon = gtk_image_new_from_icon_name (MODEST_TOOLBAR_ICON_MAIL_SEND, HILDON_ICON_SIZE_FINGER);
950 gtk_container_add (GTK_CONTAINER (priv->send_button), send_icon);
951 gtk_widget_set_size_request (GTK_WIDGET (priv->send_button), 148, -1);
953 g_object_unref (title_size_group);
954 g_object_unref (value_size_group);
956 priv->brand_icon = gtk_image_new ();
957 gtk_misc_set_alignment (GTK_MISC (priv->brand_icon), 0.5, 0.5);
958 priv->brand_label = gtk_label_new (NULL);
959 hildon_helper_set_logical_font (priv->brand_label, "SmallSystemFont");
960 gtk_misc_set_alignment (GTK_MISC (priv->brand_label), 0.0, 0.5);
961 gtk_widget_set_no_show_all (priv->brand_icon, TRUE);
962 gtk_widget_set_no_show_all (priv->brand_label, TRUE);
964 from_send_hbox = gtk_hbox_new (FALSE, 0);
965 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->from_field, TRUE, TRUE, 0);
966 gtk_box_pack_start (GTK_BOX (from_send_hbox), priv->send_button, FALSE, FALSE, 0);
968 branding_box = gtk_hbox_new (FALSE, MODEST_MARGIN_DEFAULT);
969 gtk_widget_show (branding_box);
970 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_label, FALSE, FALSE, 0);
971 gtk_box_pack_start (GTK_BOX (branding_box), priv->brand_icon, FALSE, FALSE, 0);
973 priv->brand_container = gtk_alignment_new (0.0, 0.5, 0.0, 1.0);
974 gtk_alignment_set_padding (GTK_ALIGNMENT (priv->brand_container), 0, 0, MODEST_MARGIN_DOUBLE, 0);
975 gtk_container_add (GTK_CONTAINER (priv->brand_container), branding_box);
976 gtk_widget_set_no_show_all (priv->brand_container, TRUE);
979 gtk_box_pack_start (GTK_BOX (priv->header_box), from_send_hbox, FALSE, FALSE, 0);
980 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
981 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
982 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
983 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
984 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
985 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->brand_container, FALSE, FALSE, 0);
986 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
988 init_wp_text_view_style ();
990 priv->msg_body = modest_wp_text_view_new ();
993 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
994 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
995 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
996 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
997 #if (GTK_MINOR_VERSION >= 10)
998 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), NULL);
999 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
1001 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
1002 deserialize_type, TRUE);
1004 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1006 priv->find_toolbar = hildon_find_toolbar_new (NULL);
1007 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
1009 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
1011 priv->pannable = hildon_pannable_area_new ();
1013 g_object_set (G_OBJECT (priv->pannable), "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1015 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
1016 window_align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
1017 gtk_alignment_set_padding (GTK_ALIGNMENT (window_align), 0, 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DEFAULT);
1019 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
1020 gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 0);
1021 gtk_container_add (GTK_CONTAINER (window_align), main_vbox);
1023 hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (priv->pannable), window_align);
1024 gtk_widget_show_all (GTK_WIDGET(priv->pannable));
1026 window_box = gtk_vbox_new (FALSE, 0);
1027 gtk_container_add (GTK_CONTAINER(obj), window_box);
1029 gtk_box_pack_start (GTK_BOX (window_box), priv->pannable, TRUE, TRUE, 0);
1031 /* Set window icon */
1032 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
1034 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1035 g_object_unref (window_icon);
1040 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
1042 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1044 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
1045 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1046 priv->clipboard_change_handler_id))
1047 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
1048 priv->clipboard_change_handler_id);
1049 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
1050 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1051 priv->default_clipboard_change_handler_id))
1052 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
1053 priv->default_clipboard_change_handler_id);
1055 if (priv->account_removed_handler_id &&
1056 g_signal_handler_is_connected (modest_runtime_get_account_store (),
1057 priv->account_removed_handler_id))
1058 g_signal_handler_disconnect(modest_runtime_get_account_store (),
1059 priv->account_removed_handler_id);
1063 modest_msg_edit_window_finalize (GObject *obj)
1065 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1067 if (priv->max_chars_banner) {
1068 g_object_weak_unref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, obj);
1069 priv->max_chars_banner = FALSE;
1072 /* Sanity check: shouldn't be needed, the window mgr should
1073 call this function before */
1074 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
1076 if (priv->font_dialog != NULL) {
1077 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
1080 if (priv->clipboard_text != NULL) {
1081 g_free (priv->clipboard_text);
1082 priv->clipboard_text = NULL;
1085 if (priv->draft_msg != NULL) {
1086 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
1087 if (TNY_IS_HEADER (header)) {
1088 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1089 modest_window_mgr_unregister_header (mgr, header);
1091 g_object_unref (priv->draft_msg);
1092 priv->draft_msg = NULL;
1094 if (priv->outbox_msg != NULL) {
1095 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
1096 if (TNY_IS_HEADER (header)) {
1097 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1098 modest_window_mgr_unregister_header (mgr, header);
1100 g_object_unref (priv->outbox_msg);
1101 priv->outbox_msg = NULL;
1103 if (priv->correct_scroll_idle > 0) {
1104 g_source_remove (priv->correct_scroll_idle);
1105 priv->correct_scroll_idle = 0;
1107 if (priv->scroll_drag_timeout_id > 0) {
1108 g_source_remove (priv->scroll_drag_timeout_id);
1109 priv->scroll_drag_timeout_id = 0;
1111 if (priv->clipboard_owner_idle > 0) {
1112 g_source_remove (priv->clipboard_owner_idle);
1113 priv->clipboard_owner_idle = 0;
1115 if (priv->original_account_name)
1116 g_free (priv->original_account_name);
1117 if (priv->original_mailbox)
1118 g_free (priv->original_mailbox);
1119 g_free (priv->msg_uid);
1120 g_free (priv->last_search);
1121 g_free (priv->references);
1122 g_free (priv->in_reply_to);
1123 g_object_unref (priv->attachments);
1124 g_object_unref (priv->images);
1126 /* This had to stay alive for as long as the picker that used it: */
1127 modest_pair_list_free (priv->from_field_protos);
1129 G_OBJECT_CLASS(parent_class)->finalize (obj);
1133 pixbuf_size_prepared (GdkPixbufLoader *loader,
1136 ModestMsgEditWindow *self)
1138 gint new_height, new_width;
1141 new_height = height;
1145 if (width > IMAGE_MAX_WIDTH) {
1146 new_height = height * IMAGE_MAX_WIDTH / width;
1147 new_width = IMAGE_MAX_WIDTH;
1150 gdk_pixbuf_loader_set_size (loader, new_width, new_height);
1154 pixbuf_from_stream (TnyStream *stream,
1155 const gchar *mime_type,
1156 guint64 *stream_size,
1157 ModestMsgEditWindow *self)
1159 GdkPixbufLoader *loader;
1162 GError *error = NULL;
1166 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1168 if (loader == NULL) {
1173 g_signal_connect (G_OBJECT (loader), "size-prepared", G_CALLBACK (pixbuf_size_prepared), self);
1175 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE);
1177 tny_stream_reset (TNY_STREAM (stream));
1178 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1179 unsigned char read_buffer[128];
1181 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1183 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1186 /* Allow some UI responsiveness */
1187 while (gtk_events_pending ())
1188 gtk_main_iteration ();
1190 hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), FALSE);
1192 gdk_pixbuf_loader_close (loader, &error);
1195 g_error_free (error);
1196 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1198 g_object_ref (pixbuf);
1199 g_object_unref (loader);
1204 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1205 GdkPixbuf *new_pixbuf;
1207 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1208 gdk_pixbuf_get_width (pixbuf);
1209 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1210 g_object_unref (pixbuf);
1211 pixbuf = new_pixbuf;
1215 *stream_size = size;
1221 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1223 ModestMsgEditWindowPrivate *priv;
1226 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1228 g_object_ref (self);
1229 for (iter = tny_list_create_iterator (attachments);
1230 !tny_iterator_is_done (iter);
1231 tny_iterator_next (iter)) {
1232 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1233 const gchar *cid = tny_mime_part_get_content_id (part);
1234 const gchar *mime_type = tny_mime_part_get_content_type (part);
1235 if ((cid != NULL)&&(mime_type != NULL)) {
1236 guint64 stream_size;
1237 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1238 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, self);
1241 g_object_unref (stream);
1243 if (pixbuf != NULL) {
1244 priv->images_count ++;
1245 priv->images_size += stream_size;
1246 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1247 g_object_unref (pixbuf);
1250 g_object_unref (part);
1252 g_object_unref (iter);
1253 g_object_unref (self);
1257 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1259 TnyMimePart *parent = NULL;
1260 const gchar *content_type = NULL;
1261 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1263 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1265 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1266 parent = g_object_ref (msg);
1267 } else if (content_type && !g_ascii_strcasecmp (content_type, "multipart/mixed")) {
1268 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1271 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1272 iter = tny_list_create_iterator (parts);
1273 while (!tny_iterator_is_done (iter)) {
1275 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1276 content_type = tny_mime_part_get_content_type (part);
1277 if (content_type && !g_ascii_strcasecmp (content_type, "multipart/related")) {
1281 g_object_unref (part);
1283 tny_iterator_next (iter);
1285 g_object_unref (iter);
1286 g_object_unref (parts);
1289 if (parent != NULL) {
1290 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1293 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1294 iter = tny_list_create_iterator (parts);
1295 while (!tny_iterator_is_done (iter)) {
1297 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1298 content_type = tny_mime_part_get_content_type (part);
1299 if (content_type && g_str_has_prefix (content_type, "image/")) {
1300 tny_list_prepend (priv->images, (GObject *) part);
1302 g_object_unref (part);
1303 tny_iterator_next (iter);
1305 g_object_unref (iter);
1306 g_object_unref (parts);
1307 g_object_unref (parent);
1312 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1315 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1317 for (iter = tny_list_create_iterator (attachments) ;
1318 !tny_iterator_is_done (iter);
1319 tny_iterator_next (iter)) {
1320 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1321 const gchar *cid = tny_mime_part_get_content_id (part);
1323 char *invalid = NULL;
1324 gint int_cid = strtol (cid, &invalid, 10);
1325 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1326 priv->next_cid = int_cid + 1;
1329 g_object_unref (part);
1331 g_object_unref (iter);
1335 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1338 gchar *to, *cc, *bcc, *subject;
1340 ModestMsgEditWindowPrivate *priv;
1341 ModestWindowPrivate *parent_priv;
1343 TnyHeaderFlags priority_flags;
1344 TnyFolder *msg_folder;
1345 gboolean is_html = FALSE;
1346 gboolean field_view_set;
1348 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1349 g_return_if_fail (TNY_IS_MSG (msg));
1351 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1352 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1354 header = tny_msg_get_header (msg);
1355 to = tny_header_dup_to (header);
1356 cc = tny_header_dup_cc (header);
1357 bcc = tny_header_dup_bcc (header);
1358 subject = tny_header_dup_subject (header);
1360 modest_tny_msg_get_references (TNY_MSG (msg), NULL, &(priv->references), &(priv->in_reply_to));
1361 priority_flags = tny_header_get_priority (header);
1364 gchar *quoted_names = modest_text_utils_quote_names (to);
1365 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), quoted_names);
1366 g_free (quoted_names);
1369 field_view_set = TRUE;
1371 gchar *quoted_names = modest_text_utils_quote_names (cc);
1372 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), quoted_names);
1373 g_free (quoted_names);
1374 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1375 gtk_widget_show (priv->cc_caption);
1376 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1377 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1378 gtk_widget_hide (priv->cc_caption);
1379 field_view_set = FALSE;
1381 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button), field_view_set);
1383 field_view_set = TRUE;
1385 gchar *quoted_names = modest_text_utils_quote_names (bcc);
1386 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), quoted_names);
1387 g_free (quoted_names);
1388 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1389 gtk_widget_show (priv->bcc_caption);
1390 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1391 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1392 gtk_widget_hide (priv->bcc_caption);
1393 field_view_set = FALSE;
1395 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button), field_view_set);
1399 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1400 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1403 update_window_title (self);
1405 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1406 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1408 if ((body == NULL)||(body[0] == '\0')) {
1410 body = modest_text_utils_convert_to_html ("");
1413 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1414 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1417 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1420 /* Add attachments to the view */
1421 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1422 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1423 if (tny_list_get_length (priv->attachments) == 0) {
1424 gtk_widget_hide (priv->attachments_caption);
1426 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1427 gtk_widget_show_all (priv->attachments_caption);
1429 get_related_images (self, msg);
1430 update_next_cid (self, priv->attachments);
1431 update_next_cid (self, priv->images);
1432 replace_with_images (self, priv->images);
1434 if (preserve_is_rich && !is_html) {
1435 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1436 /* Get the default format required from configuration */
1437 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1438 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1441 /* Set the default focus depending on having already a To: field or not */
1442 if ((!to)||(*to == '\0')) {
1443 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1445 gtk_widget_grab_focus (priv->msg_body);
1448 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1450 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1451 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1453 modest_msg_edit_window_set_modified (self, FALSE);
1455 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1456 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1457 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1458 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1460 if (priv->msg_uid) {
1461 g_free (priv->msg_uid);
1462 priv->msg_uid = NULL;
1465 /* we should set a reference to the incoming message if it is a draft */
1466 msg_folder = tny_msg_get_folder (msg);
1468 if (modest_tny_folder_is_local_folder (msg_folder)) {
1469 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1470 if (type == TNY_FOLDER_TYPE_INVALID)
1471 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1473 if (type == TNY_FOLDER_TYPE_DRAFTS)
1474 priv->draft_msg = g_object_ref(msg);
1475 if (type == TNY_FOLDER_TYPE_OUTBOX)
1476 priv->outbox_msg = g_object_ref(msg);
1477 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1479 g_object_unref (msg_folder);
1490 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1492 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1493 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1494 GtkWidget *placeholder;
1495 GtkWidget *tool_item;
1500 GtkWidget *sizes_menu;
1501 GtkWidget *fonts_menu;
1507 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1508 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (parent_priv->toolbar), FALSE);
1509 gtk_toolbar_set_icon_size (GTK_TOOLBAR (parent_priv->toolbar), HILDON_ICON_SIZE_FINGER);
1510 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1512 /* Font color placeholder */
1513 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1514 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1517 priv->font_color_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1518 priv->font_color_button = hildon_color_button_new ();
1519 gtk_widget_set_size_request (priv->font_color_button, -1, 48);
1520 GTK_WIDGET_UNSET_FLAGS (priv->font_color_toolitem, GTK_CAN_FOCUS);
1521 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1522 gtk_container_add (GTK_CONTAINER (priv->font_color_toolitem), priv->font_color_button);
1523 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1524 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->font_color_toolitem), TRUE);
1525 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->font_color_toolitem), insert_index);
1526 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1528 G_CALLBACK (modest_msg_edit_window_color_button_change),
1531 /* Font size and face placeholder */
1532 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1533 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1535 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1536 priv->size_tool_button_label = gtk_label_new (NULL);
1537 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1538 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1539 size_text, "</span>", NULL);
1540 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1541 gtk_misc_set_alignment (GTK_MISC (priv->size_tool_button_label), 1.0, 0.5);
1543 hildon_helper_set_logical_font (priv->size_tool_button_label, "LargeSystemFont");
1544 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1545 gtk_box_pack_start (GTK_BOX (hbox), priv->size_tool_button_label, TRUE, TRUE, 0);
1546 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1547 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1548 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1549 gtk_widget_set_sensitive (arrow, FALSE);
1550 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1551 sizes_menu = gtk_menu_new ();
1552 priv->sizes_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1553 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1556 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1557 gtk_list_store_append (GTK_LIST_STORE (priv->sizes_model), &iter);
1559 gtk_list_store_set (GTK_LIST_STORE (priv->sizes_model), &iter,
1563 if (wp_font_size[size_index] == 12)
1564 priv->current_size_index = size_index;
1568 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_size_clicked), window);
1569 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1570 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1571 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1572 priv->font_size_toolitem = tool_item;
1575 tool_item = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
1576 priv->font_tool_button_label = gtk_label_new (NULL);
1577 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1578 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1579 gtk_misc_set_alignment (GTK_MISC (priv->font_tool_button_label), 1.0, 0.5);
1581 hildon_helper_set_logical_font (priv->font_tool_button_label, "LargeSystemFont");
1582 hbox = gtk_hbox_new (MODEST_MARGIN_DEFAULT, FALSE);
1583 gtk_box_pack_start (GTK_BOX (hbox), priv->font_tool_button_label, TRUE, TRUE, 0);
1584 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
1585 gtk_misc_set_alignment (GTK_MISC (arrow), 0.0, 0.5);
1586 gtk_box_pack_start (GTK_BOX (hbox), arrow, TRUE, TRUE, 0);
1587 gtk_widget_set_sensitive (arrow, FALSE);
1588 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), hbox);
1589 fonts_menu = gtk_menu_new ();
1590 priv->faces_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
1591 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1594 gtk_list_store_append (GTK_LIST_STORE (priv->faces_model), &iter);
1596 gtk_list_store_set (GTK_LIST_STORE (priv->faces_model), &iter,
1597 0, wp_get_font_name (font_index),
1600 if (font_index == DEFAULT_FONT)
1601 priv->current_face_index = font_index;
1603 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (font_face_clicked), window);
1604 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1605 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1606 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1607 priv->font_face_toolitem = tool_item;
1609 /* Set expand and homogeneous for remaining items */
1610 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1611 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1612 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1613 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1614 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1615 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1617 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1618 will not show the tool items added to the placeholders) */
1619 gtk_widget_show_all (parent_priv->toolbar);
1621 /* Set the no show all *after* showing all items. We do not
1622 want the toolbar to be shown with a show all because it
1623 could go agains the gconf setting regarding showing or not
1624 the toolbar of the editor window */
1625 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1631 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, const gchar *mailbox, gboolean preserve_is_rich)
1634 ModestWindowPrivate *parent_priv;
1635 ModestMsgEditWindowPrivate *priv;
1636 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1637 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1638 ModestWindowMgr *mgr = NULL;
1640 g_return_val_if_fail (msg, NULL);
1641 g_return_val_if_fail (account_name, NULL);
1643 mgr = modest_runtime_get_window_mgr ();
1645 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1647 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1648 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1650 /* Menubar. Update the state of some toggles */
1651 priv->from_field_protos = get_transports ();
1652 priv->original_mailbox = NULL;
1653 modest_selector_picker_set_pair_list (MODEST_SELECTOR_PICKER (priv->from_field), priv->from_field_protos);
1654 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1655 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1656 if (mailbox && modest_pair_list_find_by_first_as_string (priv->from_field_protos, mailbox)) {
1657 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) mailbox);
1658 priv->original_mailbox = g_strdup (mailbox);
1659 } else if (modest_account_mgr_account_is_multimailbox (modest_runtime_get_account_mgr (), account_name, NULL)) {
1660 /* We set the first mailbox as the active mailbox */
1661 priv->original_mailbox = multimailbox_get_default_mailbox (account_name);
1662 if (priv->original_mailbox != NULL)
1663 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1664 (gpointer) priv->original_mailbox);
1666 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field),
1667 (gpointer) account_name);
1669 modest_selector_picker_set_active_id (MODEST_SELECTOR_PICKER (priv->from_field), (gpointer) account_name);
1671 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1672 update_branding (MODEST_MSG_EDIT_WINDOW (obj), priv->last_from_account);
1673 hildon_button_set_title (HILDON_BUTTON (priv->from_field),
1675 hildon_button_set_value (HILDON_BUTTON (priv->from_field),
1676 hildon_touch_selector_get_current_text
1677 (HILDON_TOUCH_SELECTOR (hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (priv->from_field)))));
1678 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1679 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1682 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1684 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1686 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1687 modest_window_set_active_mailbox (MODEST_WINDOW(obj), priv->original_mailbox);
1689 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1691 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1692 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1693 /* Add common dimming rules */
1694 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1695 modest_msg_edit_window_toolbar_dimming_entries,
1696 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1697 MODEST_WINDOW (obj));
1698 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_toolitem,
1699 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1700 MODEST_WINDOW (obj));
1701 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1702 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1703 MODEST_WINDOW (obj));
1704 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1705 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1706 MODEST_WINDOW (obj));
1707 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->send_button,
1708 G_CALLBACK (modest_ui_dimming_rules_on_send),
1709 MODEST_WINDOW (obj));
1710 /* Insert dimming rules group for this window */
1711 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1712 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1714 /* Setup app menu */
1715 setup_menu (MODEST_MSG_EDIT_WINDOW (obj));
1717 /* Checks the dimming rules */
1718 g_object_unref (toolbar_rules_group);
1719 g_object_unref (clipboard_rules_group);
1720 gtk_widget_hide (priv->priority_icon);
1721 gtk_widget_queue_resize (priv->subject_box);
1722 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1724 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1726 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1727 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1728 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1729 priv->update_caption_visibility = TRUE;
1731 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1733 /* Track account-removed signal, this window should be closed
1734 in the case we're creating a mail associated to the account
1736 priv->account_removed_handler_id =
1737 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1739 G_CALLBACK(on_account_removed),
1742 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1744 return (ModestWindow*) obj;
1748 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1750 GString **string_buffer = (GString **) user_data;
1752 *string_buffer = g_string_append (*string_buffer, buffer);
1758 * @result: A new string which should be freed with g_free().
1761 get_formatted_data (ModestMsgEditWindow *edit_window)
1763 ModestMsgEditWindowPrivate *priv;
1764 GString *string_buffer = g_string_new ("");
1766 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1768 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1770 modest_text_utils_hyperlinkify (string_buffer);
1772 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1774 return g_string_free (string_buffer, FALSE);
1779 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1782 const gchar *account_name;
1783 ModestMsgEditWindowPrivate *priv;
1784 TnyIterator *att_iter;
1785 const gchar *picker_active_id;
1787 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1791 picker_active_id = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
1792 g_return_val_if_fail (picker_active_id, NULL);
1793 account_name = modest_utils_get_account_name_from_recipient (picker_active_id, NULL);
1795 /* don't free these (except from) */
1796 data = g_slice_new0 (MsgData);
1797 data->from = g_strdup ((gchar *) modest_selector_picker_get_active_display_name (MODEST_SELECTOR_PICKER (priv->from_field)));
1798 data->account_name = g_strdup (account_name);
1799 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1800 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1801 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1802 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1803 data->references = g_strdup (priv->references);
1804 data->in_reply_to = g_strdup (priv->in_reply_to);
1805 if (priv->draft_msg) {
1806 data->draft_msg = g_object_ref (priv->draft_msg);
1807 } else if (priv->outbox_msg) {
1808 data->draft_msg = g_object_ref (priv->outbox_msg);
1810 data->draft_msg = NULL;
1813 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1815 gtk_text_buffer_get_bounds (buf, &b, &e);
1816 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1818 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1819 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1821 data->html_body = NULL;
1823 /* deep-copy the data */
1824 att_iter = tny_list_create_iterator (priv->attachments);
1825 data->attachments = NULL;
1826 while (!tny_iterator_is_done (att_iter)) {
1827 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1828 if (!(TNY_IS_MIME_PART(part))) {
1829 g_warning ("strange data in attachment list");
1830 g_object_unref (part);
1831 tny_iterator_next (att_iter);
1834 data->attachments = g_list_append (data->attachments,
1836 tny_iterator_next (att_iter);
1838 g_object_unref (att_iter);
1840 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1841 att_iter = tny_list_create_iterator (priv->images);
1842 data->images = NULL;
1843 while (!tny_iterator_is_done (att_iter)) {
1844 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1846 if (!(TNY_IS_MIME_PART(part))) {
1847 g_warning ("strange data in attachment list");
1848 g_object_unref (part);
1849 tny_iterator_next (att_iter);
1852 cid = tny_mime_part_get_content_id (part);
1854 gchar *image_tag_id;
1855 GtkTextTag *image_tag;
1857 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1858 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1859 g_free (image_tag_id);
1861 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1863 ((gtk_text_iter_has_tag (&iter, image_tag))||
1864 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1865 data->images = g_list_append (data->images,
1866 g_object_ref (part));
1868 g_object_unref (part);
1869 tny_iterator_next (att_iter);
1871 g_object_unref (att_iter);
1873 data->priority_flags = priv->priority_flags;
1880 unref_gobject (GObject *obj, gpointer data)
1882 if (!G_IS_OBJECT(obj))
1884 g_object_unref (obj);
1888 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1891 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1899 g_free (data->from);
1900 g_free (data->subject);
1901 g_free (data->plain_body);
1902 g_free (data->html_body);
1903 g_free (data->account_name);
1904 g_free (data->references);
1905 g_free (data->in_reply_to);
1907 if (data->draft_msg != NULL) {
1908 g_object_unref (data->draft_msg);
1909 data->draft_msg = NULL;
1912 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1913 g_list_free (data->attachments);
1914 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1915 g_list_free (data->images);
1917 g_slice_free (MsgData, data);
1921 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1923 guint64 *parts_size)
1925 ModestMsgEditWindowPrivate *priv;
1927 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1929 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1931 /* TODO: add images */
1932 *parts_size += priv->images_size;
1933 *parts_count += priv->images_count;
1938 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1941 ModestMsgEditWindowPrivate *priv = NULL;
1942 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1944 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1946 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1948 return MODEST_MSG_EDIT_FORMAT_HTML;
1950 return MODEST_MSG_EDIT_FORMAT_TEXT;
1954 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1955 ModestMsgEditFormat format)
1957 ModestMsgEditWindowPrivate *priv;
1958 ModestWindowPrivate *parent_priv;
1960 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1961 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1962 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1965 case MODEST_MSG_EDIT_FORMAT_HTML:
1966 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1967 if (parent_priv->toolbar) gtk_widget_show (parent_priv->toolbar);
1969 case MODEST_MSG_EDIT_FORMAT_TEXT:
1970 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1971 if (parent_priv->toolbar) gtk_widget_hide (parent_priv->toolbar);
1974 g_return_if_reached ();
1978 ModestMsgEditFormatState *
1979 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1981 ModestMsgEditFormatState *format_state = NULL;
1982 ModestMsgEditWindowPrivate *priv;
1983 WPTextBufferFormat *buffer_format;
1985 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1987 buffer_format = g_new0 (WPTextBufferFormat, 1);
1988 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1990 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1992 format_state = g_new0 (ModestMsgEditFormatState, 1);
1993 format_state->bold = buffer_format->bold&0x1;
1994 format_state->italics = buffer_format->italic&0x1;
1995 format_state->bullet = buffer_format->bullet&0x1;
1996 format_state->color = buffer_format->color;
1997 format_state->font_size = buffer_format->font_size;
1998 format_state->font_family = wp_get_font_name (buffer_format->font);
1999 format_state->justification = buffer_format->justification;
2000 g_free (buffer_format);
2002 return format_state;
2007 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
2008 const ModestMsgEditFormatState *format_state)
2010 ModestMsgEditWindowPrivate *priv;
2011 WPTextBufferFormat *buffer_format;
2012 WPTextBufferFormat *current_format;
2014 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2015 g_return_if_fail (format_state != NULL);
2017 buffer_format = g_new0 (WPTextBufferFormat, 1);
2018 current_format = g_new0 (WPTextBufferFormat, 1);
2020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2021 gtk_widget_grab_focus (priv->msg_body);
2022 buffer_format->bold = (format_state->bold != FALSE);
2023 buffer_format->italic = (format_state->italics != FALSE);
2024 buffer_format->color = format_state->color;
2025 buffer_format->font_size = format_state->font_size;
2026 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
2027 buffer_format->justification = format_state->justification;
2028 buffer_format->bullet = format_state->bullet;
2030 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
2032 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
2033 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
2034 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
2035 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
2036 buffer_format->cs.font = (buffer_format->font != current_format->font);
2037 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
2038 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
2040 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
2041 if (buffer_format->cs.bold) {
2042 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
2043 GINT_TO_POINTER (buffer_format->bold&0x1));
2045 if (buffer_format->cs.italic) {
2046 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
2047 GINT_TO_POINTER (buffer_format->italic&0x1));
2049 if (buffer_format->cs.color) {
2050 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2051 GINT_TO_POINTER (&(buffer_format->color)));
2053 if (buffer_format->cs.font_size) {
2054 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2055 GINT_TO_POINTER (buffer_format->font_size));
2057 if (buffer_format->cs.justification) {
2058 switch (buffer_format->justification) {
2059 case GTK_JUSTIFY_LEFT:
2060 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
2061 GINT_TO_POINTER(TRUE));
2063 case GTK_JUSTIFY_CENTER:
2064 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
2065 GINT_TO_POINTER(TRUE));
2067 case GTK_JUSTIFY_RIGHT:
2068 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
2069 GINT_TO_POINTER(TRUE));
2076 if (buffer_format->cs.font) {
2077 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2078 GINT_TO_POINTER (buffer_format->font));
2080 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
2081 if (buffer_format->cs.bullet) {
2082 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
2083 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
2085 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
2087 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
2089 g_free (buffer_format);
2090 g_free (current_format);
2092 /* Check dimming rules */
2093 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
2094 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
2098 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
2100 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2102 ModestWindowPrivate *parent_priv;
2103 ModestMsgEditWindowPrivate *priv;
2105 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2106 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2108 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
2109 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu");
2110 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2111 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2113 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatPlainTextMenu");
2114 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
2115 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
2118 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2120 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2121 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
2123 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2124 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
2126 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
2127 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
2130 switch (buffer_format->justification)
2132 case GTK_JUSTIFY_LEFT:
2133 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2135 case GTK_JUSTIFY_CENTER:
2136 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2138 case GTK_JUSTIFY_RIGHT:
2139 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2146 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
2148 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
2149 G_CALLBACK (modest_msg_edit_window_color_button_change),
2151 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
2152 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
2153 G_CALLBACK (modest_msg_edit_window_color_button_change),
2156 if (priv->current_size_index != buffer_format->font_size) {
2160 path = gtk_tree_path_new_from_indices (buffer_format->font_size, -1);
2161 if (gtk_tree_model_get_iter (priv->sizes_model, &iter, path)) {
2165 priv->current_size_index = buffer_format->font_size;
2167 gtk_tree_model_get (priv->sizes_model, &iter, 0, &size_text, -1);
2168 markup = g_strconcat ("<span font_family='Sans'>",
2169 size_text, "</span>", NULL);
2171 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2175 gtk_tree_path_free (path);
2178 if (priv->current_face_index != buffer_format->font) {
2182 path = gtk_tree_path_new_from_indices (buffer_format->font, -1);
2183 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2187 priv->current_face_index = buffer_format->font;
2188 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2189 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2190 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2197 g_free (buffer_format);
2201 #ifdef MODEST_HILDON_VERSION_0
2203 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2206 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2207 ModestMsgEditWindowPrivate *priv;
2208 GtkWidget *dialog = NULL;
2210 GdkColor *new_color = NULL;
2212 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2213 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2215 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2216 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2217 g_free (buffer_format);
2219 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2220 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2221 if (new_color != NULL) {
2222 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2223 (gpointer) new_color);
2226 gtk_widget_destroy (dialog);
2231 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2234 ModestMsgEditWindowPrivate *priv;
2235 GtkWidget *dialog = NULL;
2237 GdkColor *old_color = NULL;
2238 const GdkColor *new_color = NULL;
2240 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2241 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2243 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2244 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2246 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2247 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2248 if (new_color != NULL)
2249 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2251 gtk_widget_destroy (dialog);
2257 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2260 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2261 ModestMsgEditWindowPrivate *priv;
2262 GtkWidget *dialog = NULL;
2264 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2265 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2267 dialog = hildon_color_chooser_new ();
2268 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2269 g_free (buffer_format);
2271 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2273 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2274 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2277 gtk_widget_destroy (dialog);
2282 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2285 ModestMsgEditWindowPrivate *priv;
2286 GtkWidget *dialog = NULL;
2287 GdkColor *old_color = NULL;
2289 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2290 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2292 dialog = hildon_color_chooser_new ();
2293 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2295 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2297 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2298 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2300 gtk_widget_destroy (dialog);
2303 #endif /*!MODEST_HILDON_VERSION_0*/
2308 create_stream_for_uri (const gchar* uri)
2313 TnyStream *result = NULL;
2315 GnomeVFSHandle *handle = NULL;
2316 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2317 if (test == GNOME_VFS_OK) {
2318 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2319 /* Streams over OBEX (Bluetooth) are not seekable but
2320 * we expect them to be (we might need to read them
2321 * several times). So if this is a Bluetooth URI just
2322 * read the whole file into memory (this is not a fast
2323 * protocol so we can assume that these files are not
2324 * going to be very big) */
2325 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2326 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2327 TnyStream *memstream = tny_camel_mem_stream_new ();
2328 tny_stream_write_to_stream (vfssstream, memstream);
2329 g_object_unref (vfssstream);
2332 result = vfssstream;
2340 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2343 ModestMsgEditWindowPrivate *priv;
2344 GtkWidget *dialog = NULL;
2346 GSList *uris = NULL;
2347 GSList *uri_node = NULL;
2349 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2351 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2352 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2353 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2355 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2357 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2358 GTK_WINDOW (dialog), GTK_WINDOW (window));
2360 response = gtk_dialog_run (GTK_DIALOG (dialog));
2362 case GTK_RESPONSE_OK:
2364 gchar *current_folder;
2365 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2366 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2367 if (current_folder && current_folder != '\0') {
2369 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_INSERT_IMAGE_PATH,
2370 current_folder, &err);
2372 g_debug ("Error storing latest used folder: %s", err->message);
2376 g_free (current_folder);
2382 gtk_widget_destroy (dialog);
2384 g_object_ref (window);
2385 /* The operation could take some time so allow the dialog to be closed */
2386 while (gtk_events_pending ())
2387 gtk_main_iteration ();
2389 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2391 GnomeVFSHandle *handle = NULL;
2392 GnomeVFSResult result;
2393 GtkTextIter position;
2394 GtkTextMark *insert_mark;
2396 uri = (const gchar *) uri_node->data;
2397 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2398 if (result == GNOME_VFS_OK) {
2400 GnomeVFSFileInfo *info;
2401 gchar *filename, *basename, *escaped_filename;
2402 TnyMimePart *mime_part;
2404 const gchar *mime_type = NULL;
2405 GnomeVFSURI *vfs_uri;
2406 guint64 stream_size;
2408 gnome_vfs_close (handle);
2409 vfs_uri = gnome_vfs_uri_new (uri);
2411 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2412 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2413 g_free (escaped_filename);
2414 gnome_vfs_uri_unref (vfs_uri);
2415 info = gnome_vfs_file_info_new ();
2417 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2418 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2420 mime_type = gnome_vfs_file_info_get_mime_type (info);
2422 mime_part = tny_platform_factory_new_mime_part
2423 (modest_runtime_get_platform_factory ());
2425 TnyStream *stream = create_stream_for_uri (uri);
2427 if (stream == NULL) {
2429 modest_platform_information_banner (NULL, NULL,
2430 _FM("sfil_ib_opening_not_allowed"));
2432 g_object_unref (mime_part);
2433 gnome_vfs_file_info_unref (info);
2437 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2439 content_id = g_strdup_printf ("%d", priv->next_cid);
2440 tny_mime_part_set_content_id (mime_part, content_id);
2441 g_free (content_id);
2444 basename = g_path_get_basename (filename);
2445 tny_mime_part_set_filename (mime_part, basename);
2448 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size, window);
2450 if (pixbuf != NULL) {
2451 priv->images_size += stream_size;
2452 priv->images_count ++;
2453 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2454 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2455 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position,
2456 tny_mime_part_get_content_id (mime_part), pixbuf);
2457 g_object_unref (pixbuf);
2459 tny_list_prepend (priv->images, (GObject *) mime_part);
2460 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2462 modest_platform_information_banner (NULL, NULL,
2463 _("mail_ib_file_operation_failed"));
2467 g_object_unref (mime_part);
2468 gnome_vfs_file_info_unref (info);
2472 g_object_unref (window);
2476 on_attach_file_response (GtkDialog *dialog,
2480 GSList *uris = NULL;
2482 GnomeVFSFileSize total_size, allowed_size;
2483 ModestMsgEditWindow *window;
2484 ModestMsgEditWindowPrivate *priv;
2489 case GTK_RESPONSE_OK:
2491 gchar *current_folder;
2493 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2494 current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog));
2495 if (current_folder && current_folder != '\0') {
2497 modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_ATTACH_FILE_PATH,
2498 current_folder, &err);
2500 g_debug ("Error storing latest used folder: %s", err->message);
2504 g_free (current_folder);
2511 window = MODEST_MSG_EDIT_WINDOW (user_data);
2512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2514 /* allowed size is the maximum size - what's already there */
2515 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2516 &att_num, &att_size);
2517 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2520 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2522 const gchar *uri = (const gchar *) uri_node->data;
2525 modest_msg_edit_window_attach_file_one (window, uri, allowed_size);
2527 if (total_size > allowed_size) {
2528 g_debug ("%s: total size: %u",
2529 __FUNCTION__, (unsigned int)total_size);
2532 allowed_size -= total_size;
2534 g_slist_foreach (uris, (GFunc) g_free, NULL);
2535 g_slist_free (uris);
2537 gtk_widget_destroy (GTK_WIDGET (dialog));
2541 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2543 GtkWidget *dialog = NULL;
2544 ModestMsgEditWindowPrivate *priv;
2547 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2551 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2554 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
2555 GTK_FILE_CHOOSER_ACTION_OPEN);
2556 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2557 conf_folder = modest_conf_get_string (modest_runtime_get_conf (),
2558 MODEST_CONF_LATEST_ATTACH_FILE_PATH, NULL);
2559 if (conf_folder && conf_folder[0] != '\0') {
2560 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), conf_folder);
2563 /* Set the default folder to documents folder */
2564 docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS));
2567 docs_folder = g_build_filename (g_getenv (MODEST_MAEMO_UTILS_MYDOCS_ENV),
2568 ".documents", NULL);
2570 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), docs_folder);
2571 g_free (docs_folder);
2573 g_free (conf_folder);
2574 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2575 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2576 GTK_WINDOW (dialog), GTK_WINDOW (window));
2578 /* Connect to response & show */
2579 g_signal_connect (dialog, "response",
2580 G_CALLBACK (on_attach_file_response), window);
2581 gtk_widget_show (dialog);
2586 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2588 GnomeVFSFileSize allowed_size)
2591 GnomeVFSHandle *handle = NULL;
2592 ModestMsgEditWindowPrivate *priv;
2593 GnomeVFSResult result;
2594 GnomeVFSFileSize size = 0;
2595 g_return_val_if_fail (window, 0);
2596 g_return_val_if_fail (uri, 0);
2598 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2600 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2601 if (result == GNOME_VFS_OK) {
2602 TnyMimePart *mime_part;
2604 const gchar *mime_type = NULL;
2606 gchar *escaped_filename;
2609 GnomeVFSFileInfo *info;
2610 GnomeVFSURI *vfs_uri;
2612 gnome_vfs_close (handle);
2613 vfs_uri = gnome_vfs_uri_new (uri);
2616 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2617 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2618 g_free (escaped_filename);
2619 gnome_vfs_uri_unref (vfs_uri);
2621 info = gnome_vfs_file_info_new ();
2623 if (gnome_vfs_get_file_info (uri,
2625 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2627 mime_type = gnome_vfs_file_info_get_mime_type (info);
2628 mime_part = tny_platform_factory_new_mime_part
2629 (modest_runtime_get_platform_factory ());
2631 /* try to get the attachment's size; this may fail for weird
2632 * file systems, like obex, upnp... */
2633 if (allowed_size != 0 &&
2634 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2636 if (size > allowed_size) {
2637 modest_platform_information_banner (NULL, NULL,
2638 _("mail_ib_error_attachment_size"));
2643 g_debug ("%s: could not get attachment size", __FUNCTION__);
2645 stream = create_stream_for_uri (uri);
2647 if (stream == NULL) {
2649 modest_platform_information_banner (NULL, NULL, _FM("sfil_ib_opening_not_allowed"));
2651 g_object_unref (mime_part);
2653 gnome_vfs_file_info_unref (info);
2657 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2658 g_object_unref (stream);
2660 content_id = g_strdup_printf ("%d", priv->next_cid);
2661 tny_mime_part_set_content_id (mime_part, content_id);
2662 g_free (content_id);
2665 basename = g_path_get_basename (filename);
2666 tny_mime_part_set_filename (mime_part, basename);
2669 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2670 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2672 info->size == 0, info->size);
2673 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2674 gtk_widget_show_all (priv->attachments_caption);
2675 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2677 g_object_unref (mime_part);
2678 gnome_vfs_file_info_unref (info);
2685 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2688 ModestMsgEditWindowPrivate *priv;
2691 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2692 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2694 if (att_list == NULL) {
2695 att_list = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2696 if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), att_list, TRUE)) {
2697 g_object_unref (att_list);
2701 g_object_ref (att_list);
2704 if (tny_list_get_length (att_list) == 0) {
2705 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2707 gboolean dialog_response;
2708 gchar *message = NULL;
2709 gchar *filename = NULL;
2711 if (tny_list_get_length (att_list) == 1) {
2713 iter = tny_list_create_iterator (att_list);
2714 part = (TnyMimePart *) tny_iterator_get_current (iter);
2715 g_object_unref (iter);
2716 if (TNY_IS_MSG (part)) {
2717 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2719 filename = tny_header_dup_subject (header);
2720 g_object_unref (header);
2722 if (filename == NULL) {
2723 filename = g_strdup (_("mail_va_no_subject"));
2726 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2728 g_object_unref (part);
2730 filename = g_strdup ("");
2732 message = g_strdup_printf (ngettext("emev_nc_delete_attachment",
2733 "emev_nc_delete_attachments",
2734 tny_list_get_length (att_list)), filename);
2737 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2741 if (dialog_response != GTK_RESPONSE_OK) {
2742 g_object_unref (att_list);
2746 for (iter = tny_list_create_iterator (att_list);
2747 !tny_iterator_is_done (iter);
2748 tny_iterator_next (iter)) {
2749 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2750 const gchar *att_id;
2751 tny_list_remove (priv->attachments, (GObject *) mime_part);
2753 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2755 if (tny_list_get_length (priv->attachments) == 0)
2756 gtk_widget_hide (priv->attachments_caption);
2757 att_id = tny_mime_part_get_content_id (mime_part);
2759 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2761 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2762 g_object_unref (mime_part);
2764 g_object_unref (iter);
2767 g_object_unref (att_list);
2769 /* if the last attachment has been removed, focus the Subject: field */
2770 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2771 gtk_widget_grab_focus (priv->subject_field);
2775 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2778 ModestMsgEditWindowPrivate *priv;
2779 GdkColor *new_color;
2780 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2782 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2783 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2786 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2788 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2790 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2792 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2797 font_size_clicked (GtkToolButton *button,
2798 ModestMsgEditWindow *window)
2800 ModestMsgEditWindowPrivate *priv;
2801 GtkWidget *selector, *dialog;
2803 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2805 selector = hildon_touch_selector_new ();
2806 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector), priv->sizes_model, TRUE);
2807 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_size_index);
2809 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2810 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2811 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_size"));
2813 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2817 WPTextBufferFormat format;
2819 new_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2821 memset (&format, 0, sizeof (format));
2822 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2824 format.cs.font_size = TRUE;
2825 format.cs.text_position = TRUE;
2826 format.cs.font = TRUE;
2827 format.font_size = new_index;
2828 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2830 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2831 GINT_TO_POINTER (new_index)))
2832 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2834 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2835 size_text = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector));
2836 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
2837 size_text, "</span>", NULL);
2839 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2843 gtk_widget_destroy (dialog);
2845 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2850 font_face_clicked (GtkToolButton *button,
2851 ModestMsgEditWindow *window)
2853 ModestMsgEditWindowPrivate *priv;
2854 GtkWidget *selector, *dialog;
2855 GtkCellRenderer *renderer;
2857 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2859 selector = hildon_touch_selector_new ();
2860 renderer = gtk_cell_renderer_text_new ();
2861 g_object_set (G_OBJECT (renderer), "alignment", PANGO_ALIGN_CENTER, "xalign", 0.5, NULL);
2862 hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector), priv->faces_model,
2863 renderer, "family", 0, "text", 0, NULL);
2864 hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, priv->current_face_index);
2866 dialog = hildon_picker_dialog_new (GTK_WINDOW (window));
2867 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (dialog), HILDON_TOUCH_SELECTOR (selector));
2868 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_font_face"));
2870 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2871 gint new_font_index;
2875 new_font_index = hildon_touch_selector_get_active (HILDON_TOUCH_SELECTOR (selector), 0);
2876 path = gtk_tree_path_new_from_indices (new_font_index, -1);
2877 if (gtk_tree_model_get_iter (priv->faces_model, &iter, path)) {
2881 gtk_tree_model_get (priv->faces_model, &iter, 0, &face_name, -1);
2883 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2884 GINT_TO_POINTER(new_font_index)))
2885 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2887 markup = g_strconcat ("<span font_family='", face_name, "'>Tt</span>", NULL);
2888 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2890 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2894 gtk_tree_path_free (path);
2897 gtk_widget_destroy (dialog);
2899 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2904 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2907 ModestMsgEditWindowPrivate *priv = NULL;
2908 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2910 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2911 if (!priv->update_caption_visibility)
2914 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2916 gtk_widget_show (priv->cc_caption);
2918 gtk_widget_hide (priv->cc_caption);
2920 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2924 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2927 ModestMsgEditWindowPrivate *priv = NULL;
2928 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2930 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2931 if (!priv->update_caption_visibility)
2934 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2936 gtk_widget_show (priv->bcc_caption);
2938 gtk_widget_hide (priv->bcc_caption);
2940 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2944 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2945 ModestRecptEditor *editor)
2947 ModestMsgEditWindowPrivate *priv;
2949 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2950 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2952 /* we check for low-mem; in that case, show a warning, and don't allow
2953 * for the addressbook
2955 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2958 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2960 if (editor == NULL) {
2961 GtkWidget *view_focus, *parent;
2962 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2964 /* This code should be kept in sync with ModestRecptEditor. The
2965 textview inside the recpt editor is the one that really gets the
2966 focus. As it's inside a scrolled window, and this one inside the
2967 hbox recpt editor inherits from, we'll need to go up in the
2968 hierarchy to know if the text view is part of the recpt editor
2969 or if it's a different text entry */
2970 parent = gtk_widget_get_parent (view_focus);
2971 if (parent && MODEST_IS_RECPT_EDITOR (parent))
2972 editor = MODEST_RECPT_EDITOR (parent);
2975 editor = MODEST_RECPT_EDITOR (priv->to_field);
2978 modest_address_book_select_addresses (editor, GTK_WINDOW (window));
2982 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2984 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2986 modest_msg_edit_window_open_addressbook (window, NULL);
2990 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2991 gboolean show_toolbar)
2993 ModestWindowPrivate *parent_priv;
2994 ModestMsgEditWindowPrivate *priv;
2996 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2997 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
2998 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
3000 /* We can not just use the code of
3001 modest_msg_edit_window_setup_toolbar because it has a
3002 mixture of both initialization and creation code. */
3004 gint current_format;
3005 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3006 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3007 if (current_format == MODEST_FILE_FORMAT_PLAIN_TEXT) {
3008 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3010 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
3013 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
3018 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
3019 TnyHeaderFlags priority_flags)
3021 ModestMsgEditWindowPrivate *priv;
3022 ModestWindowPrivate *parent_priv;
3024 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3026 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3027 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3029 if (priv->priority_flags != priority_flags) {
3030 GtkAction *priority_action = NULL;
3032 priv->priority_flags = priority_flags;
3034 switch (priority_flags) {
3035 case TNY_HEADER_FLAG_HIGH_PRIORITY:
3036 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3037 MODEST_HEADER_ICON_HIGH,
3038 HILDON_ICON_SIZE_SMALL);
3039 gtk_widget_show (priv->priority_icon);
3040 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3041 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
3043 case TNY_HEADER_FLAG_LOW_PRIORITY:
3044 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon),
3045 MODEST_HEADER_ICON_LOW,
3046 HILDON_ICON_SIZE_SMALL);
3047 gtk_widget_show (priv->priority_icon);
3048 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3049 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
3052 gtk_widget_hide (priv->priority_icon);
3053 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
3054 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
3057 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
3058 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3060 gtk_widget_queue_resize (priv->subject_box);
3064 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
3067 ModestMsgEditWindowPrivate *priv;
3068 ModestWindowPrivate *parent_priv;
3069 gint current_format;
3071 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3073 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3074 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3076 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
3077 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
3079 gtk_widget_set_no_show_all (GTK_WIDGET (parent_priv->toolbar), TRUE);
3081 if (current_format != file_format) {
3082 switch (file_format) {
3083 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
3084 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
3085 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
3086 if (parent_priv->toolbar)
3087 gtk_widget_show (parent_priv->toolbar);
3089 case MODEST_FILE_FORMAT_PLAIN_TEXT:
3093 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
3094 response = gtk_dialog_run (GTK_DIALOG (dialog));
3095 gtk_widget_destroy (dialog);
3096 if (response == GTK_RESPONSE_OK) {
3097 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
3098 if (parent_priv->toolbar)
3099 gtk_widget_hide (parent_priv->toolbar);
3101 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatFormattedTextMenu"));
3102 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
3107 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3108 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3109 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3114 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
3117 ModestMsgEditWindowPrivate *priv;
3118 WPTextBufferFormat oldfmt, fmt;
3119 gint old_position = 0;
3123 GdkColor *color = NULL;
3124 gboolean bold, bold_set, italic, italic_set;
3125 gboolean underline, underline_set;
3126 gboolean strikethrough, strikethrough_set;
3127 gboolean position_set;
3128 gboolean font_size_set, font_set, color_set;
3131 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3132 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3134 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
3135 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
3136 GTK_WINDOW(dialog), GTK_WINDOW (window));
3138 /* First we get the currently selected font information */
3139 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
3141 switch (oldfmt.text_position) {
3142 case TEXT_POSITION_NORMAL:
3145 case TEXT_POSITION_SUPERSCRIPT:
3153 g_object_set (G_OBJECT (dialog),
3154 "bold", oldfmt.bold != FALSE,
3155 "bold-set", !oldfmt.cs.bold,
3156 "underline", oldfmt.underline != FALSE,
3157 "underline-set", !oldfmt.cs.underline,
3158 "italic", oldfmt.italic != FALSE,
3159 "italic-set", !oldfmt.cs.italic,
3160 "strikethrough", oldfmt.strikethrough != FALSE,
3161 "strikethrough-set", !oldfmt.cs.strikethrough,
3162 "color", &oldfmt.color,
3163 "color-set", !oldfmt.cs.color,
3164 "size", wp_font_size[oldfmt.font_size],
3165 "size-set", !oldfmt.cs.font_size,
3166 "position", old_position,
3167 "position-set", !oldfmt.cs.text_position,
3168 "family", wp_get_font_name (oldfmt.font),
3169 "family-set", !oldfmt.cs.font,
3172 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
3173 GTK_WINDOW (dialog), GTK_WINDOW (window));
3174 gtk_widget_show_all (dialog);
3175 priv->font_dialog = dialog;
3176 response = gtk_dialog_run (GTK_DIALOG (dialog));
3177 priv->font_dialog = NULL;
3178 if (response == GTK_RESPONSE_OK) {
3180 g_object_get( dialog,
3182 "bold-set", &bold_set,
3183 "underline", &underline,
3184 "underline-set", &underline_set,
3186 "italic-set", &italic_set,
3187 "strikethrough", &strikethrough,
3188 "strikethrough-set", &strikethrough_set,
3190 "color-set", &color_set,
3192 "size-set", &font_size_set,
3193 "family", &font_name,
3194 "family-set", &font_set,
3195 "position", &position,
3196 "position-set", &position_set,
3201 if (response == GTK_RESPONSE_OK) {
3202 memset(&fmt, 0, sizeof(fmt));
3208 fmt.italic = italic;
3209 fmt.cs.italic = TRUE;
3211 if (underline_set) {
3212 fmt.underline = underline;
3213 fmt.cs.underline = TRUE;
3215 if (strikethrough_set) {
3216 fmt.strikethrough = strikethrough;
3217 fmt.cs.strikethrough = TRUE;
3222 ? TEXT_POSITION_NORMAL
3223 : ( ( position == 1 )
3224 ? TEXT_POSITION_SUPERSCRIPT
3225 : TEXT_POSITION_SUBSCRIPT );
3226 fmt.cs.text_position = TRUE;
3227 fmt.font_size = oldfmt.font_size;
3231 fmt.cs.color = TRUE;
3234 fmt.font = wp_get_font_index(font_name,
3239 if (font_size_set) {
3240 fmt.cs.font_size = TRUE;
3241 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
3243 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
3244 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
3246 gtk_widget_destroy (dialog);
3248 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
3252 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
3254 ModestMsgEditWindowPrivate *priv;
3255 ModestWindowPrivate *parent_priv;
3256 gboolean was_rich_text, is_rich_text;
3258 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3259 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3260 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3262 was_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3264 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
3266 is_rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
3268 if (parent_priv->toolbar && was_rich_text != is_rich_text) {
3270 gtk_widget_show (parent_priv->toolbar);
3272 gtk_widget_hide (parent_priv->toolbar);
3275 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3276 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3280 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
3282 ModestMsgEditWindowPrivate *priv;
3284 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3285 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3287 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
3289 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3290 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3295 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
3297 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3299 priv->can_undo = can_undo;
3303 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3305 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3307 priv->can_redo = can_redo;
3311 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3313 ModestMsgEditWindowPrivate *priv;
3314 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3315 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3317 return priv->can_undo;
3321 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3323 ModestMsgEditWindowPrivate *priv;
3324 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3325 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3327 return priv->can_redo;
3332 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3335 GtkTextIter match_start, match_end;
3337 if (image_id == NULL)
3340 gtk_text_buffer_get_start_iter (buffer, &iter);
3342 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3343 GSList *tags = gtk_text_iter_get_tags (&match_start);
3345 for (node = tags; node != NULL; node = g_slist_next (node)) {
3346 GtkTextTag *tag = (GtkTextTag *) node->data;
3347 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3348 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3349 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3351 offset = gtk_text_iter_get_offset (&match_start);
3352 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3353 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3357 gtk_text_iter_forward_char (&iter);
3362 message_is_empty (ModestMsgEditWindow *window)
3364 ModestMsgEditWindowPrivate *priv = NULL;
3366 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3367 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3369 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3370 * so we can ignore markup.
3372 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3375 count = gtk_text_buffer_get_char_count (buf);
3381 msg_body_focus (GtkWidget *focus,
3382 GdkEventFocus *event,
3386 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3387 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3388 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3393 recpt_field_changed (GtkTextBuffer *buffer,
3394 ModestMsgEditWindow *editor)
3396 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3397 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3401 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3403 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3404 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3408 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3411 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3412 GtkTextBuffer *buffer;
3414 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3415 gtk_text_buffer_set_modified (buffer, modified);
3416 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3417 gtk_text_buffer_set_modified (buffer, modified);
3418 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3419 gtk_text_buffer_set_modified (buffer, modified);
3420 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3424 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3426 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3427 const char *account_name;
3428 GtkTextBuffer *buffer;
3430 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3431 if (gtk_text_buffer_get_modified (buffer))
3433 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3434 if (gtk_text_buffer_get_modified (buffer))
3436 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3437 if (gtk_text_buffer_get_modified (buffer))
3439 if (gtk_text_buffer_get_modified (priv->text_buffer))
3442 account_name = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
3443 if (priv->original_mailbox) {
3444 if (!account_name || strcmp (account_name, priv->original_mailbox))
3446 } else if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3457 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3459 ModestMsgEditWindowPrivate *priv = NULL;
3460 GSList *address_list = NULL;
3462 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3463 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3465 /* check if there's no recipient added */
3466 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3467 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3468 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3469 /* no recipient contents, then select contacts */
3470 modest_msg_edit_window_open_addressbook (window, NULL);
3475 g_object_ref (window);
3476 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), &address_list)) {
3477 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3478 g_object_unref (window);
3481 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), &address_list)) {
3482 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3483 g_object_unref (window);
3486 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), &address_list)) {
3487 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3488 g_object_unref (window);
3492 /* Add contacts to address book */
3494 modest_address_book_add_address_list (address_list);
3496 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3497 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3498 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3499 g_object_unref (window);
3506 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3507 ModestMsgEditWindow *window)
3509 modest_msg_edit_window_offer_attach_file (window);
3513 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3515 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3517 return priv->clipboard_text;
3521 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3523 ModestMsgEditWindow *window)
3525 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3526 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3529 /* It could happen that the window was already closed */
3530 if (!GTK_WIDGET_VISIBLE (window))
3533 g_object_ref (window);
3534 text = gtk_clipboard_wait_for_text (selection_clipboard);
3536 if (priv->clipboard_text != NULL) {
3537 g_free (priv->clipboard_text);
3539 priv->clipboard_text = text;
3541 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3543 g_object_unref (window);
3546 static gboolean clipboard_owner_change_idle (gpointer userdata)
3548 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3549 ModestMsgEditWindowPrivate *priv;
3551 gdk_threads_enter ();
3552 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3553 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3555 priv->clipboard_owner_idle = 0;
3556 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3557 gdk_threads_leave ();
3563 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3565 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3566 if (priv->clipboard_owner_idle == 0) {
3567 priv->clipboard_owner_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
3568 clipboard_owner_change_idle,
3569 g_object_ref (window),
3575 subject_field_move_cursor (GtkEntry *entry,
3576 GtkMovementStep step,
3581 /* It could happen that the window was already closed */
3582 if (!GTK_WIDGET_VISIBLE (window))
3585 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3589 update_window_title (ModestMsgEditWindow *window)
3591 ModestMsgEditWindowPrivate *priv = NULL;
3592 const gchar *subject;
3594 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3595 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3596 if (subject == NULL || subject[0] == '\0')
3597 subject = _("mail_va_new_email");
3599 gtk_window_set_title (GTK_WINDOW (window), subject);
3605 body_insert_text (GtkTextBuffer *buffer,
3606 GtkTextIter *location,
3609 ModestMsgEditWindow *window)
3611 GtkTextIter end_iter;
3618 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3620 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end_iter);
3622 offset = gtk_text_iter_get_offset (&end_iter);
3623 line = gtk_text_iter_get_line (&end_iter);
3627 while (text_offset < text + len) {
3628 if (*text_offset == '\n')
3630 if (text_lines + line >= MAX_BODY_LINES) {
3631 len = text_offset - text;
3637 utf8_len = g_utf8_strlen (text, len);
3639 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3640 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3641 if (line <= MAX_BODY_LINES && offset < MAX_BODY_LENGTH)
3646 utf8_end = g_utf8_offset_to_pointer (text, MAX_BODY_LENGTH - offset);
3648 /* Prevent endless recursion */
3649 result = g_strndup (text, utf8_end - text);
3650 g_signal_handlers_block_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3651 g_signal_emit_by_name (G_OBJECT (buffer), "insert-text", location,
3652 (gpointer) result, (gpointer) (utf8_end - text),
3654 g_signal_handlers_unblock_by_func (G_OBJECT (buffer), G_CALLBACK (body_insert_text), window);
3658 if (line > MAX_BODY_LINES || offset + utf8_len > MAX_BODY_LENGTH) {
3659 if (priv->max_chars_banner == NULL) {
3660 priv->max_chars_banner = hildon_banner_show_information (GTK_WIDGET (window), NULL,
3661 _CS("ckdg_ib_maximum_characters_reached"));
3662 g_object_weak_ref (G_OBJECT (priv->max_chars_banner), (GWeakNotify) max_chars_banner_unref, window);
3668 subject_field_changed (GtkEditable *editable,
3669 ModestMsgEditWindow *window)
3671 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3672 update_window_title (window);
3673 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3674 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3675 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3678 subject_field_insert_text (GtkEditable *editable,
3680 gint new_text_length,
3682 ModestMsgEditWindow *window)
3684 GString *result = g_string_new ("");
3686 gint result_len = 0;
3687 const gchar *entry_text = NULL;
3690 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3691 old_length = g_utf8_strlen (entry_text, -1);
3693 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3694 gunichar c = g_utf8_get_char_validated (current, 8);
3695 /* Invalid unichar, stop */
3701 result = g_string_append_unichar (result, c);
3705 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3706 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3709 /* Prevent endless recursion */
3710 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3711 g_signal_emit_by_name (editable, "insert-text",
3712 (gpointer) result->str, (gpointer) result->len,
3713 (gpointer) position, (gpointer) window);
3714 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3718 if (result_len + old_length > 1000) {
3719 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3720 _CS("ckdg_ib_maximum_characters_reached"));
3722 g_string_free (result, TRUE);
3726 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3729 ModestMsgEditWindowPrivate *priv = NULL;
3731 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3734 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3737 gtk_widget_show_all (priv->find_toolbar);
3738 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3740 gtk_widget_hide_all (priv->find_toolbar);
3741 gtk_widget_grab_focus (priv->msg_body);
3746 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3748 GtkTextIter *match_start,
3749 GtkTextIter *match_end)
3751 GtkTextIter end_iter;
3752 gchar *str_casefold;
3755 gchar *range_casefold;
3758 gboolean result = FALSE;
3765 gtk_text_iter_forward_to_end (&end_iter);
3767 str_casefold = g_utf8_casefold (str, -1);
3768 str_chars_n = strlen (str);
3770 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3771 range_casefold = g_utf8_casefold (range_text, -1);
3772 range_chars_n = strlen (range_casefold);
3774 if (range_chars_n < str_chars_n) {
3775 g_free (str_casefold);
3776 g_free (range_text);
3777 g_free (range_casefold);
3781 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3782 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3783 if (!g_utf8_collate (range_subtext, str_casefold)) {
3784 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3786 if (!gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3787 match_start, match_end, NULL)) {
3788 g_debug ("Matched string with collate, but not matched in model");
3790 g_free (found_text);
3792 g_free (range_subtext);
3796 g_free (str_casefold);
3797 g_free (range_text);
3798 g_free (range_casefold);
3805 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3806 ModestMsgEditWindow *window)
3808 gchar *current_search = NULL;
3809 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3811 GtkTextIter selection_start, selection_end;
3812 GtkTextIter match_start, match_end;
3813 gboolean continue_search = FALSE;
3815 if (message_is_empty (window)) {
3816 g_free (priv->last_search);
3817 priv->last_search = NULL;
3818 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3822 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3823 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3824 g_free (current_search);
3825 g_free (priv->last_search);
3826 priv->last_search = NULL;
3827 /* Information banner about empty search */
3828 hildon_banner_show_information (NULL, NULL, _CS("ecdg_ib_find_rep_enter_text"));
3832 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3833 continue_search = TRUE;
3835 g_free (priv->last_search);
3836 priv->last_search = g_strdup (current_search);
3839 if (continue_search) {
3840 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3841 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3842 &match_start, &match_end);
3844 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_search_complete"));
3846 GtkTextIter buffer_start;
3847 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3848 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3849 &match_start, &match_end);
3851 hildon_banner_show_information (NULL, NULL, _HL("ckct_ib_find_no_matches"));
3854 /* Mark as selected the string found in search */
3856 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3857 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3858 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3860 g_free (priv->last_search);
3861 priv->last_search = NULL;
3863 g_free (current_search);
3867 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3869 ModestMsgEditWindowPrivate *priv;
3871 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3876 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3879 ModestMsgEditWindowPrivate *priv;
3881 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3886 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3887 ModestMsgEditWindow *window)
3889 modest_msg_edit_window_toggle_find_toolbar (window, FALSE);
3893 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3896 ModestMsgEditWindowPrivate *priv;
3897 TnyHeader *header = NULL;
3899 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3900 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3904 if (priv->draft_msg != NULL) {
3905 g_object_unref (priv->draft_msg);
3908 if (draft != NULL) {
3909 g_object_ref (draft);
3910 header = tny_msg_get_header (draft);
3911 if (priv->msg_uid) {
3912 g_free (priv->msg_uid);
3913 priv->msg_uid = NULL;
3915 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3918 priv->draft_msg = draft;
3922 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3923 GtkTextIter *start, GtkTextIter *end,
3926 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3927 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3930 if (tag == NULL) return;
3931 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3932 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3933 replace_with_images (window, priv->images);
3938 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3941 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3943 g_return_if_fail (TNY_IS_MIME_PART (part));
3944 tny_list_prepend (priv->attachments, (GObject *) part);
3945 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3946 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3947 gtk_widget_show_all (priv->attachments_caption);
3948 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3952 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3954 ModestMsgEditWindowPrivate *priv;
3956 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3959 return priv->msg_uid;
3963 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3964 ModestMsgEditWindowWidgetType widget_type)
3966 ModestMsgEditWindowPrivate *priv;
3968 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3969 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3971 switch (widget_type) {
3972 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3973 return priv->msg_body;
3975 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3976 return priv->to_field;
3978 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3979 return priv->cc_field;
3981 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3982 return priv->bcc_field;
3984 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3985 return priv->subject_field;
3987 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3988 return priv->attachments_view;
3996 remove_tags (WPTextBuffer *buffer)
3998 GtkTextIter start, end;
4000 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
4001 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
4003 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
4007 on_account_removed (TnyAccountStore *account_store,
4008 TnyAccount *account,
4011 /* Do nothing if it's a store account, because we use the
4012 transport to send the messages */
4013 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
4014 const gchar *parent_acc = NULL;
4015 const gchar *our_acc = NULL;
4017 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
4018 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
4019 /* Close this window if I'm showing a message of the removed account */
4020 if (strcmp (parent_acc, our_acc) == 0)
4021 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
4026 update_signature (ModestMsgEditWindow *self,
4027 const gchar *old_account,
4028 const gchar *new_account)
4030 ModestMsgEditWindowPrivate *priv;
4031 gboolean has_old_signature, has_new_signature;
4033 ModestAccountMgr *mgr;
4036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4038 gtk_text_buffer_begin_user_action (priv->text_buffer);
4040 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
4041 mgr = modest_runtime_get_account_mgr ();
4045 signature = modest_account_mgr_get_signature_from_recipient (mgr, old_account, &has_old_signature);
4046 if (has_old_signature) {
4047 GtkTextIter match_start, match_end;
4049 MODEST_TEXT_UTILS_SIGNATURE_MARKER as it
4050 seems that the search has some problems
4051 with the blank space at the end */
4052 if (gtk_text_iter_forward_search (&iter, "--",
4053 GTK_TEXT_SEARCH_TEXT_ONLY,
4054 &match_start, NULL, NULL)) {
4055 gtk_text_buffer_get_end_iter (priv->text_buffer ,&match_end);
4056 gtk_text_buffer_delete (priv->text_buffer, &match_start, &match_end);
4058 } else if (gtk_text_iter_forward_search (&iter, _("mcen_ia_editor_original_message"), 0,
4059 &match_start, &match_end, NULL)) {
4066 priv->last_from_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4067 signature = modest_account_mgr_get_signature_from_recipient (mgr, new_account, &has_new_signature);
4068 if (has_new_signature) {
4069 gchar *full_signature = g_strconcat (MODEST_TEXT_UTILS_SIGNATURE_MARKER, "\n",
4071 gtk_text_buffer_insert (priv->text_buffer, &iter, full_signature, -1);
4072 g_free (full_signature);
4075 gtk_text_buffer_end_user_action (priv->text_buffer);
4078 static void update_branding (ModestMsgEditWindow *self,
4079 const gchar *new_account)
4081 ModestMsgEditWindowPrivate *priv;
4082 ModestAccountMgr *mgr;
4083 const GdkPixbuf *new_icon = NULL;
4084 gchar *new_label = NULL;
4085 gboolean show = FALSE;
4087 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4089 mgr = modest_runtime_get_account_mgr ();
4091 modest_account_mgr_get_branding_from_recipient (mgr, new_account, &new_label, &new_icon, MODEST_ICON_SIZE_SMALL);
4093 gtk_image_set_from_pixbuf (GTK_IMAGE (priv->brand_icon), (GdkPixbuf *) new_icon);
4094 gtk_widget_show (priv->brand_icon);
4097 gtk_widget_hide (priv->brand_icon);
4100 gtk_label_set_text (GTK_LABEL (priv->brand_label), new_label);
4101 gtk_widget_show (priv->brand_label);
4105 gtk_widget_hide (priv->brand_label);
4109 gtk_widget_show (priv->brand_container);
4111 gtk_widget_hide (priv->brand_container);
4115 from_field_changed (HildonPickerButton *button,
4116 ModestMsgEditWindow *self)
4118 ModestMsgEditWindowPrivate *priv;
4119 gchar *old_account, *new_account;
4121 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4123 old_account = priv->last_from_account;
4124 new_account = modest_selector_picker_get_active_id (MODEST_SELECTOR_PICKER (priv->from_field));
4127 g_warning ("%s, could not get the new account", __FUNCTION__);
4131 /* If the From is the same do nothing */
4132 if (old_account && new_account && !strcmp (old_account, new_account))
4135 priv->last_from_account = new_account;
4137 update_signature (self, old_account, new_account);
4138 update_branding (self, new_account);
4142 typedef struct _MessageSettingsHelper {
4143 ModestMsgEditWindow *window;
4144 GSList *priority_group;
4145 GSList *format_group;
4146 GtkToggleButton *current_priority;
4147 GtkToggleButton *current_format;
4148 } MessageSettingsHelper;
4151 on_priority_toggle (GtkToggleButton *button,
4152 MessageSettingsHelper *helper)
4155 ModestMsgEditWindowPrivate *priv;
4157 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4158 if (gtk_toggle_button_get_active (button)) {
4160 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4161 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4162 if ((node_button != button) &&
4163 gtk_toggle_button_get_active (node_button)) {
4164 gtk_toggle_button_set_active (node_button, FALSE);
4167 helper->current_priority = button;
4169 gboolean found = FALSE;
4170 /* If no one is active, activate it again */
4171 for (node = helper->priority_group; node != NULL; node = g_slist_next (node)) {
4172 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4173 if (gtk_toggle_button_get_active (node_button)) {
4179 gtk_toggle_button_set_active (button, TRUE);
4185 on_format_toggle (GtkToggleButton *button,
4186 MessageSettingsHelper *helper)
4189 ModestMsgEditWindowPrivate *priv;
4191 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (helper->window);
4192 if (gtk_toggle_button_get_active (button)) {
4194 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4195 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4196 if ((node_button != button) &&
4197 gtk_toggle_button_get_active (node_button)) {
4198 gtk_toggle_button_set_active (node_button, FALSE);
4201 helper->current_format = button;
4203 gboolean found = FALSE;
4204 /* If no one is active, activate it again */
4205 for (node = helper->format_group; node != NULL; node = g_slist_next (node)) {
4206 GtkToggleButton *node_button = (GtkToggleButton *) node->data;
4207 if (gtk_toggle_button_get_active (node_button)) {
4213 gtk_toggle_button_set_active (button, TRUE);
4220 modest_msg_edit_window_show_msg_settings_dialog (ModestMsgEditWindow *window)
4225 GtkWidget *priority_hbox;
4226 GtkWidget *high_toggle, *medium_toggle, *low_toggle;
4227 GtkWidget *captioned;
4228 GtkSizeGroup *title_sizegroup, *value_sizegroup;
4229 GtkWidget *format_hbox;
4230 GtkWidget *html_toggle, *text_toggle;
4231 ModestMsgEditWindowPrivate *priv;
4232 MessageSettingsHelper helper = {0,};
4234 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4235 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
4236 helper.window = window;
4237 helper.priority_group = NULL;
4238 helper.format_group = NULL;
4240 title_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4241 value_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4243 dialog = gtk_dialog_new_with_buttons (_("mcen_me_message_settings"), NULL,
4244 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
4245 _HL("wdgt_bd_done"), GTK_RESPONSE_ACCEPT, NULL);
4246 vbox = gtk_vbox_new (FALSE, 0);
4247 align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
4248 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, MODEST_MARGIN_DOUBLE, MODEST_MARGIN_DOUBLE, 0);
4249 gtk_container_add (GTK_CONTAINER (align), vbox);
4250 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), align);
4251 gtk_widget_show (align);
4252 gtk_widget_show (vbox);
4254 /* Priority toggles */
4255 priority_hbox = gtk_hbox_new (TRUE, 0);
4256 high_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4257 gtk_button_set_label (GTK_BUTTON (high_toggle), _("mcen_me_editor_priority_high"));
4258 helper.priority_group = g_slist_prepend (helper.priority_group, high_toggle);
4259 g_object_set_data (G_OBJECT (high_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_HIGH_PRIORITY));
4260 medium_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4261 gtk_button_set_label (GTK_BUTTON (medium_toggle), _("mcen_me_editor_priority_normal"));
4262 helper.priority_group = g_slist_prepend (helper.priority_group, medium_toggle);
4263 g_object_set_data (G_OBJECT (medium_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_NORMAL_PRIORITY));
4264 low_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4265 gtk_button_set_label (GTK_BUTTON (low_toggle), _("mcen_me_editor_priority_low"));
4266 helper.priority_group = g_slist_prepend (helper.priority_group, low_toggle);
4267 g_object_set_data (G_OBJECT (low_toggle), "priority", GINT_TO_POINTER (TNY_HEADER_FLAG_LOW_PRIORITY));
4268 gtk_box_pack_start (GTK_BOX (priority_hbox), low_toggle, TRUE, TRUE, 0);
4269 gtk_box_pack_start (GTK_BOX (priority_hbox), medium_toggle, TRUE, TRUE, 0);
4270 gtk_box_pack_start (GTK_BOX (priority_hbox), high_toggle, TRUE, TRUE, 0);
4271 gtk_widget_show_all (priority_hbox);
4272 captioned = modest_maemo_utils_create_captioned (title_sizegroup, value_sizegroup,
4273 _("mcen_me_editor_message_priority"), FALSE, priority_hbox);
4274 gtk_widget_show (captioned);
4275 gtk_box_pack_start (GTK_BOX (vbox), captioned, FALSE, FALSE, 0);
4277 /* format toggles */
4278 format_hbox = gtk_hbox_new (TRUE, 0);
4279 html_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4280 gtk_button_set_label (GTK_BUTTON (html_toggle), _("mcen_me_editor_formatted_text"));
4281 helper.format_group = g_slist_prepend (helper.format_group, html_toggle);
4282 g_object_set_data (G_OBJECT (html_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_HTML));
4283 g_object_set_data (G_OBJECT (html_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_FORMATTED_TEXT));
4284 text_toggle = hildon_gtk_toggle_button_new (HILDON_SIZE_FINGER_HEIGHT);
4285 gtk_button_set_label (GTK_BUTTON (text_toggle), _("mcen_me_editor_plain_text"));
4286 helper.format_group = g_slist_prepend (helper.format_group, text_toggle);
4287 g_object_set_data (G_OBJECT (text_toggle), "format", GINT_TO_POINTER (MODEST_MSG_EDIT_FORMAT_TEXT));
4288 g_object_set_data (G_OBJECT (text_toggle), "file-format", GINT_TO_POINTER (MODEST_FILE_FORMAT_PLAIN_TEXT));
4289 gtk_box_pack_start (GTK_BOX (format_hbox), html_toggle, TRUE, TRUE, 0);
4290 gtk_box_pack_start (GTK_BOX (format_hbox), text_toggle, TRUE, TRUE, 0);
4291 gtk_widget_show_all (format_hbox);
4292 gtk_widget_show (format_hbox);
4293 gtk_box_pack_start (GTK_BOX (vbox), format_hbox, FALSE, FALSE, 0);
4296 g_object_unref (title_sizegroup);
4297 g_object_unref (value_sizegroup);
4299 /* Set current values */
4300 switch (priv->priority_flags) {
4301 case TNY_HEADER_FLAG_HIGH_PRIORITY:
4302 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (high_toggle), TRUE);
4303 helper.current_priority = GTK_TOGGLE_BUTTON (high_toggle);
4305 case TNY_HEADER_FLAG_LOW_PRIORITY:
4306 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (low_toggle), TRUE);
4307 helper.current_priority = GTK_TOGGLE_BUTTON (low_toggle);
4310 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (medium_toggle), TRUE);
4311 helper.current_priority = GTK_TOGGLE_BUTTON (medium_toggle);
4315 switch (modest_msg_edit_window_get_format (window)) {
4316 case MODEST_MSG_EDIT_FORMAT_TEXT:
4317 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_toggle), TRUE);
4318 helper.current_format = GTK_TOGGLE_BUTTON (text_toggle);
4320 case MODEST_MSG_EDIT_FORMAT_HTML:
4322 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (html_toggle), TRUE);
4323 helper.current_format = GTK_TOGGLE_BUTTON (html_toggle);
4327 /* Signal connects */
4328 g_signal_connect (G_OBJECT (high_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4329 g_signal_connect (G_OBJECT (medium_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4330 g_signal_connect (G_OBJECT (low_toggle), "toggled", G_CALLBACK (on_priority_toggle), &helper);
4331 g_signal_connect (G_OBJECT (html_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4332 g_signal_connect (G_OBJECT (text_toggle), "toggled", G_CALLBACK (on_format_toggle), &helper);
4334 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4335 GTK_WINDOW (dialog), GTK_WINDOW (window));
4337 /* Save settings if the user clicked on done */
4338 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
4339 TnyHeaderFlags flags;
4340 ModestMsgEditFormat old_format, new_format;
4342 /* Set priority flags */
4343 flags = (TnyHeaderFlags) g_object_get_data (G_OBJECT (helper.current_priority), "priority");
4344 if (priv->priority_flags != flags)
4345 modest_msg_edit_window_set_priority_flags (window, flags);
4347 /* Set edit format */
4348 old_format = modest_msg_edit_window_get_format (window);
4349 new_format = (ModestMsgEditFormat) g_object_get_data (G_OBJECT (helper.current_format), "format");
4350 if (old_format != new_format) {
4351 gint file_format = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (helper.current_format), "file-format"));
4352 modest_msg_edit_window_set_file_format (window, file_format);
4356 gtk_widget_destroy (dialog);
4357 g_slist_free (helper.priority_group);
4361 on_message_settings (GtkAction *action,
4362 ModestMsgEditWindow *window)
4364 modest_msg_edit_window_show_msg_settings_dialog (window);
4368 on_cc_button_toggled (HildonCheckButton *button,
4369 ModestMsgEditWindow *window)
4371 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4373 modest_msg_edit_window_show_cc (MODEST_MSG_EDIT_WINDOW (window),
4374 hildon_check_button_get_active (button));
4378 on_bcc_button_toggled (HildonCheckButton *button,
4379 ModestMsgEditWindow *window)
4381 g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
4383 modest_msg_edit_window_show_bcc (MODEST_MSG_EDIT_WINDOW (window),
4384 hildon_check_button_get_active (button));
4388 setup_menu (ModestMsgEditWindow *self)
4390 ModestMsgEditWindowPrivate *priv = NULL;
4392 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4394 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4396 /* Settings menu buttons */
4397 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_checknames"), NULL,
4398 APP_MENU_CALLBACK (modest_ui_actions_on_check_names),
4400 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_undo"), "<Ctrl>z",
4401 APP_MENU_CALLBACK (modest_ui_actions_on_undo),
4402 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_undo));
4404 priv->cc_button = hildon_check_button_new (0);
4405 gtk_button_set_label (GTK_BUTTON (priv->cc_button), _("mcen_me_editor_showcc"));
4406 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->cc_button),
4408 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->cc_button),
4410 g_signal_connect (G_OBJECT (priv->cc_button), "toggled",
4411 G_CALLBACK (on_cc_button_toggled), (gpointer) self);
4412 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4413 gtk_button_set_alignment (GTK_BUTTON (priv->cc_button), 0.5, 0.5);
4415 priv->bcc_button = hildon_check_button_new (0);
4416 gtk_button_set_label (GTK_BUTTON (priv->bcc_button), _("mcen_me_editor_showbcc"));
4417 hildon_check_button_set_active (HILDON_CHECK_BUTTON (priv->bcc_button),
4419 modest_hildon2_window_add_button_to_menu (MODEST_HILDON2_WINDOW (self), GTK_BUTTON (priv->bcc_button),
4421 g_signal_connect (G_OBJECT (priv->bcc_button), "toggled",
4422 G_CALLBACK (on_bcc_button_toggled), (gpointer) self);
4423 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4424 gtk_button_set_alignment (GTK_BUTTON (priv->bcc_button), 0.5, 0.5);
4426 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_attach_inlineimage"), NULL,
4427 APP_MENU_CALLBACK (modest_ui_actions_on_insert_image),
4428 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_set_style));
4429 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_editor_add_attachment"), NULL,
4430 APP_MENU_CALLBACK (modest_msg_edit_window_add_attachment_clicked),
4432 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_remove_attachments"), NULL,
4433 APP_MENU_CALLBACK (modest_ui_actions_on_remove_attachments),
4434 MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_editor_remove_attachment));
4435 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_message_settings"), NULL,
4436 APP_MENU_CALLBACK (on_message_settings),
4438 modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), "<Ctrl>f",
4439 APP_MENU_CALLBACK (modest_ui_actions_on_toggle_find_in_page),
4444 emit_open_addressbook (GtkButton *button,
4445 ModestRecptEditor *editor)
4447 g_signal_emit_by_name (G_OBJECT (editor), "open-addressbook");
4451 _create_addressbook_box (GtkSizeGroup *title_size_group, GtkSizeGroup *value_size_group,
4452 const gchar *label, GtkWidget *control)
4454 GtkWidget *abook_button;
4457 GtkWidget *label_widget;
4459 box = gtk_hbox_new (FALSE, 0);
4461 align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
4462 gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 0, 0, MODEST_MARGIN_DEFAULT);
4464 abook_button = hildon_gtk_button_new (HILDON_SIZE_FINGER_HEIGHT);
4465 label_widget = gtk_label_new (label);
4466 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
4467 gtk_container_add (GTK_CONTAINER (abook_button), label_widget);
4469 gtk_container_add (GTK_CONTAINER (align), abook_button);
4470 gtk_widget_set_size_request (label_widget, 148 - MODEST_MARGIN_DOUBLE, -1);
4471 gtk_box_pack_start (GTK_BOX (box), align, FALSE, FALSE, 0);
4472 gtk_box_pack_start (GTK_BOX (box), control, TRUE, TRUE, 0);
4473 if (title_size_group)
4474 gtk_size_group_add_widget (title_size_group, label_widget);
4475 if (value_size_group)
4476 gtk_size_group_add_widget (value_size_group, control);
4478 g_signal_connect (G_OBJECT (abook_button), "clicked",
4479 G_CALLBACK (emit_open_addressbook), control);
4485 max_chars_banner_unref (ModestMsgEditWindow *self, GObject *old_ref)
4487 ModestMsgEditWindowPrivate *priv = NULL;
4489 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(self));
4491 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
4492 priv->max_chars_banner = NULL;