2 * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "evolution-config.h"
24 #include <glib/gi18n-lib.h>
27 #include <camel/camel.h>
28 #include <e-util/e-util.h>
29 #include <libemail-engine/libemail-engine.h>
31 #include "e-mail-notes.h"
33 #define E_TYPE_MAIL_NOTES_EDITOR \
34 (e_mail_notes_editor_get_type ())
35 #define E_MAIL_NOTES_EDITOR(obj) \
36 (G_TYPE_CHECK_INSTANCE_CAST \
37 ((obj), E_TYPE_MAIL_NOTES_EDITOR, EMailNotesEditor))
38 #define E_IS_MAIL_NOTES_EDITOR(obj) \
39 (G_TYPE_CHECK_INSTANCE_TYPE \
40 ((obj), E_TYPE_MAIL_NOTES_EDITOR))
42 typedef struct _EMailNotesEditor EMailNotesEditor
;
43 typedef struct _EMailNotesEditorClass EMailNotesEditorClass
;
45 struct _EMailNotesEditor
{
48 EHTMLEditor
*editor
; /* not referenced */
49 EAttachmentPaned
*attachment_paned
; /* not referenced */
50 EFocusTracker
*focus_tracker
;
51 GtkActionGroup
*action_group
;
54 CamelMimeMessage
*message
;
59 struct _EMailNotesEditorClass
{
60 GtkWindowClass parent_class
;
63 GType
e_mail_notes_editor_get_type (void);
65 G_DEFINE_TYPE (EMailNotesEditor
, e_mail_notes_editor
, GTK_TYPE_WINDOW
)
68 e_mail_notes_extract_text_content (CamelMimePart
*part
)
70 CamelDataWrapper
*content
;
72 GByteArray
*byte_array
;
75 g_return_val_if_fail (CAMEL_IS_MIME_PART (part
), NULL
);
77 content
= camel_medium_get_content (CAMEL_MEDIUM (part
));
78 g_return_val_if_fail (content
!= NULL
, NULL
);
80 stream
= camel_stream_mem_new ();
81 camel_data_wrapper_decode_to_stream_sync (content
, stream
, NULL
, NULL
);
82 camel_stream_close (stream
, NULL
, NULL
);
84 byte_array
= camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (stream
));
87 text
= g_strndup ((const gchar
*) byte_array
->data
, byte_array
->len
);
89 g_object_unref (stream
);
95 e_mail_notes_extract_text_from_multipart_alternative (EContentEditor
*cnt_editor
,
96 CamelMultipart
*in_multipart
)
100 g_return_if_fail (E_IS_CONTENT_EDITOR (cnt_editor
));
101 g_return_if_fail (CAMEL_IS_MULTIPART (in_multipart
));
103 nparts
= camel_multipart_get_number (in_multipart
);
105 for (ii
= 0; ii
< nparts
; ii
++) {
107 CamelContentType
*ct
;
109 /* Traverse from the end, where the best format available is stored */
110 part
= camel_multipart_get_part (in_multipart
, nparts
- ii
- 1);
114 ct
= camel_mime_part_get_content_type (part
);
118 if (camel_content_type_is (ct
, "text", "html")) {
121 text
= e_mail_notes_extract_text_content (part
);
123 e_content_editor_set_html_mode (cnt_editor
, TRUE
);
124 e_content_editor_insert_content (
127 E_CONTENT_EDITOR_INSERT_TEXT_HTML
|
128 E_CONTENT_EDITOR_INSERT_REPLACE_ALL
);
132 } else if (camel_content_type_is (ct
, "text", "plain")) {
135 text
= e_mail_notes_extract_text_content (part
);
137 e_content_editor_insert_content (
140 E_CONTENT_EDITOR_INSERT_TEXT_PLAIN
|
141 E_CONTENT_EDITOR_INSERT_REPLACE_ALL
);
150 e_mail_notes_editor_extract_text_from_multipart_related (EMailNotesEditor
*notes_editor
,
151 CamelMultipart
*multipart
)
153 EContentEditor
*cnt_editor
;
156 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
157 g_return_if_fail (CAMEL_IS_MULTIPART (multipart
));
159 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
160 nparts
= camel_multipart_get_number (multipart
);
162 for (ii
= 0; ii
< nparts
; ii
++) {
164 CamelContentType
*ct
;
165 CamelDataWrapper
*content
;
167 part
= camel_multipart_get_part (multipart
, ii
);
171 ct
= camel_mime_part_get_content_type (part
);
175 if (camel_content_type_is (ct
, "image", "*")) {
176 e_content_editor_insert_image_from_mime_part (cnt_editor
, part
);
177 } else if (camel_content_type_is (ct
, "multipart", "alternative")) {
178 content
= camel_medium_get_content (CAMEL_MEDIUM (part
));
179 if (CAMEL_IS_MULTIPART (content
))
180 e_mail_notes_extract_text_from_multipart_alternative (cnt_editor
, CAMEL_MULTIPART (content
));
186 e_mail_notes_editor_extract_text_from_part (EMailNotesEditor
*notes_editor
,
189 CamelContentType
*ct
;
190 CamelDataWrapper
*content
;
191 EContentEditor
*cnt_editor
;
193 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
194 g_return_if_fail (CAMEL_IS_MIME_PART (part
));
196 content
= camel_medium_get_content (CAMEL_MEDIUM (part
));
197 ct
= camel_data_wrapper_get_mime_type_field (content
);
199 g_return_if_fail (content
!= NULL
);
200 g_return_if_fail (ct
!= NULL
);
202 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
204 if (camel_content_type_is (ct
, "multipart", "related")) {
205 g_return_if_fail (CAMEL_IS_MULTIPART (content
));
207 e_mail_notes_editor_extract_text_from_multipart_related (notes_editor
, CAMEL_MULTIPART (content
));
208 } else if (camel_content_type_is (ct
, "multipart", "alternative")) {
209 if (CAMEL_IS_MULTIPART (content
)) {
210 e_mail_notes_extract_text_from_multipart_alternative (cnt_editor
, CAMEL_MULTIPART (content
));
212 } else if (camel_content_type_is (ct
, "text", "plain")) {
215 text
= e_mail_notes_extract_text_content (part
);
217 e_content_editor_insert_content (
220 E_CONTENT_EDITOR_INSERT_TEXT_PLAIN
|
221 E_CONTENT_EDITOR_INSERT_REPLACE_ALL
);
228 e_mail_notes_editor_extract_text_from_message (EMailNotesEditor
*notes_editor
,
229 CamelMimeMessage
*message
)
231 CamelContentType
*ct
;
232 CamelDataWrapper
*content
;
233 EContentEditor
*cnt_editor
;
235 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
236 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message
));
238 content
= camel_medium_get_content (CAMEL_MEDIUM (message
));
239 ct
= camel_data_wrapper_get_mime_type_field (content
);
241 g_return_if_fail (content
!= NULL
);
242 g_return_if_fail (ct
!= NULL
);
244 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
246 if (camel_content_type_is (ct
, "multipart", "mixed")) {
247 EAttachmentStore
*attachment_store
;
248 CamelMultipart
*multipart
;
251 g_return_if_fail (CAMEL_IS_MULTIPART (content
));
253 attachment_store
= e_attachment_view_get_store (E_ATTACHMENT_VIEW (notes_editor
->attachment_paned
));
254 multipart
= CAMEL_MULTIPART (content
);
255 nparts
= camel_multipart_get_number (multipart
);
257 /* The first part is the note text, the rest are attachments */
258 for (ii
= 0; ii
< nparts
; ii
++) {
261 part
= camel_multipart_get_part (multipart
, ii
);
265 ct
= camel_mime_part_get_content_type (part
);
270 e_mail_notes_editor_extract_text_from_part (notes_editor
, part
);
272 EAttachment
*attachment
;
274 attachment
= e_attachment_new ();
276 e_attachment_set_mime_part (attachment
, part
);
277 e_attachment_store_add_attachment (attachment_store
, attachment
);
278 e_attachment_load_async (attachment
, (GAsyncReadyCallback
)
279 e_attachment_load_handle_error
, notes_editor
);
281 g_object_unref (attachment
);
285 e_mail_notes_editor_extract_text_from_part (notes_editor
, CAMEL_MIME_PART (message
));
288 e_content_editor_set_changed (cnt_editor
, FALSE
);
291 static CamelMimeMessage
*
292 e_mail_notes_editor_encode_text_to_message (EMailNotesEditor
*notes_editor
)
294 EContentEditor
*cnt_editor
;
295 EAttachmentStore
*attachment_store
;
296 CamelMimeMessage
*message
= NULL
;
298 const gchar
*username
;
299 CamelInternetAddress
*address
;
300 gboolean has_text
= FALSE
, has_attachments
;
302 g_return_val_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
), NULL
);
303 g_return_val_if_fail (notes_editor
->editor
, NULL
);
305 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
306 g_return_val_if_fail (E_IS_CONTENT_EDITOR (cnt_editor
), NULL
);
308 message
= camel_mime_message_new ();
309 username
= g_get_user_name ();
310 if (!username
|| !*username
)
311 username
= g_get_real_name ();
312 address
= camel_internet_address_new ();
313 camel_internet_address_add (address
, NULL
, username
);
315 message_uid
= camel_header_msgid_generate (g_get_host_name ());
317 camel_mime_message_set_from (message
, address
);
318 camel_mime_message_set_date (message
, CAMEL_MESSAGE_DATE_CURRENT
, 0);
319 camel_mime_message_set_subject (message
, _("Message Note"));
320 camel_mime_message_set_message_id (message
, message_uid
);
322 g_object_unref (address
);
323 g_free (message_uid
);
325 attachment_store
= e_attachment_view_get_store (E_ATTACHMENT_VIEW (notes_editor
->attachment_paned
));
326 has_attachments
= e_attachment_store_get_num_attachments (attachment_store
) > 0;
328 if (e_content_editor_get_html_mode (cnt_editor
)) {
329 CamelMultipart
*multipart_alternative
;
330 CamelMultipart
*multipart_body
;
332 GSList
*inline_images_parts
= NULL
;
335 multipart_alternative
= camel_multipart_new ();
336 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_alternative
), "multipart/alternative");
337 camel_multipart_set_boundary (multipart_alternative
, NULL
);
339 text
= e_content_editor_get_content (
341 E_CONTENT_EDITOR_GET_TEXT_PLAIN
|
342 E_CONTENT_EDITOR_GET_PROCESSED
,
346 part
= camel_mime_part_new ();
347 camel_mime_part_set_content (part
, text
, strlen (text
), "text/plain");
348 camel_multipart_add_part (multipart_alternative
, part
);
350 g_object_unref (part
);
357 text
= e_content_editor_get_content (
359 E_CONTENT_EDITOR_GET_PROCESSED
|
360 E_CONTENT_EDITOR_GET_TEXT_HTML
|
361 E_CONTENT_EDITOR_GET_INLINE_IMAGES
,
363 &inline_images_parts
);
365 if (has_attachments
&& !has_text
&& (!text
|| !*text
)) {
366 /* Text is required, thus if there are attachments,
367 but no text, then store at least a space. */
369 text
= g_strdup (" ");
373 part
= camel_mime_part_new ();
374 camel_mime_part_set_content (part
, text
, strlen (text
), "text/html");
375 camel_multipart_add_part (multipart_alternative
, part
);
377 g_object_unref (part
);
381 g_slist_free_full (inline_images_parts
, g_object_unref
);
382 inline_images_parts
= NULL
;
387 if (inline_images_parts
) {
390 multipart_body
= camel_multipart_new ();
391 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart_body
), "multipart/related");
392 camel_multipart_set_boundary (multipart_body
, NULL
);
394 part
= camel_mime_part_new ();
395 camel_medium_set_content (CAMEL_MEDIUM (part
), CAMEL_DATA_WRAPPER (multipart_alternative
));
396 camel_multipart_add_part (multipart_body
, part
);
397 g_object_unref (part
);
399 for (link
= inline_images_parts
; link
; link
= g_slist_next (link
)) {
400 CamelMimePart
*part
= link
->data
;
405 camel_multipart_add_part (multipart_body
, part
);
408 multipart_body
= multipart_alternative
;
409 multipart_alternative
= NULL
;
412 if (has_attachments
) {
413 CamelMultipart
*multipart
;
415 multipart
= camel_multipart_new ();
416 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart
), "multipart/mixed");
417 camel_multipart_set_boundary (multipart
, NULL
);
419 part
= camel_mime_part_new ();
420 camel_medium_set_content (CAMEL_MEDIUM (part
), CAMEL_DATA_WRAPPER (multipart_body
));
421 camel_multipart_add_part (multipart
, part
);
422 g_object_unref (part
);
424 e_attachment_store_add_to_multipart (attachment_store
, multipart
, "UTF-8");
426 g_object_unref (multipart_body
);
427 multipart_body
= multipart
;
430 camel_medium_set_content (CAMEL_MEDIUM (message
), CAMEL_DATA_WRAPPER (multipart_body
));
432 g_slist_free_full (inline_images_parts
, g_object_unref
);
433 g_clear_object (&multipart_alternative
);
434 g_clear_object (&multipart_body
);
438 text
= e_content_editor_get_content (
440 E_CONTENT_EDITOR_GET_TEXT_PLAIN
|
441 E_CONTENT_EDITOR_GET_PROCESSED
,
444 if (has_attachments
&& !has_text
&& (!text
|| !*text
)) {
445 /* Text is required, thus if there are attachments,
446 but no text, then store at least a space. */
448 text
= g_strdup (" ");
452 if (has_attachments
) {
453 CamelMultipart
*multipart
;
456 multipart
= camel_multipart_new ();
457 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart
), "multipart/mixed");
458 camel_multipart_set_boundary (multipart
, NULL
);
460 part
= camel_mime_part_new ();
461 camel_mime_part_set_content (part
, text
, strlen (text
), "text/plain");
462 camel_multipart_add_part (multipart
, part
);
463 g_object_unref (part
);
465 e_attachment_store_add_to_multipart (attachment_store
, multipart
, "UTF-8");
467 camel_medium_set_content (CAMEL_MEDIUM (message
), CAMEL_DATA_WRAPPER (multipart
));
469 g_object_unref (multipart
);
471 camel_mime_part_set_content (CAMEL_MIME_PART (message
), text
, strlen (text
), "text/plain");
480 camel_mime_message_encode_8bit_parts (message
);
482 g_clear_object (&message
);
489 e_mail_notes_retrieve_message_thread (EAlertSinkThreadJobData
*job_data
,
491 GCancellable
*cancellable
,
494 EMailNotesEditor
*notes_editor
= user_data
;
495 CamelMimeMessage
*message
;
497 if (g_cancellable_set_error_if_cancelled (cancellable
, error
))
500 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
502 message
= camel_folder_get_message_sync (notes_editor
->folder
, notes_editor
->uid
, cancellable
, error
);
503 if (!g_cancellable_is_cancelled (cancellable
))
504 notes_editor
->message
= message
;
506 g_clear_object (&message
);
510 e_mail_notes_retrieve_message_done (gpointer ptr
)
512 EMailNotesEditor
*notes_editor
= ptr
;
514 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
516 if (notes_editor
->message
) {
517 EActivityBar
*activity_bar
;
518 CamelDataWrapper
*content
;
519 CamelContentType
*ct
;
521 content
= camel_medium_get_content (CAMEL_MEDIUM (notes_editor
->message
));
522 ct
= camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (notes_editor
->message
));
524 if (ct
&& camel_content_type_is (ct
, "multipart", "mixed") && CAMEL_IS_MULTIPART (content
)) {
525 CamelMultipart
*multipart
= CAMEL_MULTIPART (content
);
528 nparts
= camel_multipart_get_number (multipart
);
529 for (ii
= 0; ii
< nparts
; ii
++) {
531 CamelContentType
*ct
;
532 const gchar
*x_evolution_note
;
534 part
= camel_multipart_get_part (multipart
, ii
);
538 ct
= camel_mime_part_get_content_type (part
);
539 if (!ct
|| !camel_content_type_is (ct
, "message", "rfc822"))
542 x_evolution_note
= camel_medium_get_header (CAMEL_MEDIUM (part
), E_MAIL_NOTES_HEADER
);
543 if (x_evolution_note
) {
544 content
= camel_medium_get_content (CAMEL_MEDIUM (part
));
545 if (CAMEL_IS_MIME_MESSAGE (content
)) {
546 e_mail_notes_editor_extract_text_from_message (notes_editor
,
547 CAMEL_MIME_MESSAGE (content
));
554 g_clear_object (¬es_editor
->message
);
555 notes_editor
->had_message
= TRUE
;
557 activity_bar
= e_html_editor_get_activity_bar (notes_editor
->editor
);
558 e_activity_bar_set_activity (activity_bar
, NULL
);
562 action
= gtk_action_group_get_action (notes_editor
->action_group
, "save-and-close");
563 gtk_action_set_sensitive (action
, FALSE
);
566 g_object_unref (notes_editor
);
570 mail_notes_editor_delete_event_cb (EMailNotesEditor
*notes_editor
,
573 GtkActionGroup
*action_group
;
576 action_group
= notes_editor
->action_group
;
577 action
= gtk_action_group_get_action (action_group
, "close");
578 gtk_action_activate (action
);
584 notes_editor_activity_notify_cb (EActivityBar
*activity_bar
,
586 EMailNotesEditor
*notes_editor
)
588 EContentEditor
*cnt_editor
;
592 g_return_if_fail (E_IS_ACTIVITY_BAR (activity_bar
));
593 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
595 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
596 can_edit
= notes_editor
->had_message
&& !e_activity_bar_get_activity (activity_bar
);
598 g_object_set (cnt_editor
, "editable", can_edit
, NULL
);
600 action
= gtk_action_group_get_action (notes_editor
->action_group
, "save-and-close");
601 gtk_action_set_sensitive (action
, can_edit
);
605 e_mail_notes_replace_message_in_folder_sync (CamelFolder
*folder
,
607 CamelMimeMessage
*message
,
609 GCancellable
*cancellable
,
612 CamelMessageInfo
*mi
;
613 gboolean success
= FALSE
;
615 g_return_val_if_fail (CAMEL_IS_FOLDER (folder
), FALSE
);
616 g_return_val_if_fail (uid
!= NULL
, FALSE
);
617 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), FALSE
);
619 mi
= camel_folder_get_message_info (folder
, uid
);
621 CamelMessageInfo
*clone
;
622 gchar
*appended_uid
= NULL
;
624 clone
= camel_message_info_clone (mi
, NULL
);
625 camel_message_info_set_abort_notifications (clone
, TRUE
);
627 camel_message_info_set_user_flag (clone
, E_MAIL_NOTES_USER_FLAG
, has_note
);
629 success
= camel_folder_append_message_sync (folder
, message
, clone
,
630 &appended_uid
, cancellable
, error
);
633 camel_message_info_set_flags (mi
, CAMEL_MESSAGE_DELETED
, CAMEL_MESSAGE_DELETED
);
635 g_clear_object (&clone
);
636 g_clear_object (&mi
);
637 g_free (appended_uid
);
639 g_set_error_literal (error
, CAMEL_ERROR
, CAMEL_ERROR_GENERIC
, _("Cannot find message in its folder summary"));
646 e_mail_notes_replace_note (CamelMimeMessage
*message
,
647 CamelMimeMessage
*note
)
649 CamelMultipart
*multipart
;
651 CamelDataWrapper
*orig_content
;
652 CamelContentType
*ct
;
654 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message
), FALSE
);
656 g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (note
), FALSE
);
658 orig_content
= camel_medium_get_content (CAMEL_MEDIUM (message
));
659 ct
= camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (message
));
660 if (ct
&& camel_content_type_is (ct
, "multipart", "mixed") && CAMEL_IS_MULTIPART (orig_content
)) {
661 CamelMimePart
*content_adept
= NULL
;
662 CamelMultipart
*multipart
= CAMEL_MULTIPART (orig_content
);
665 nparts
= camel_multipart_get_number (multipart
);
666 for (ii
= 0; ii
< nparts
; ii
++) {
668 CamelContentType
*ct
;
669 const gchar
*x_evolution_note
;
671 part
= camel_multipart_get_part (multipart
, ii
);
675 ct
= camel_mime_part_get_content_type (part
);
676 if (!ct
|| !camel_content_type_is (ct
, "message", "rfc822")) {
678 content_adept
= NULL
;
681 content_adept
= part
;
685 x_evolution_note
= camel_medium_get_header (CAMEL_MEDIUM (part
), E_MAIL_NOTES_HEADER
);
686 if (x_evolution_note
)
690 content_adept
= NULL
;
693 content_adept
= part
;
697 orig_content
= camel_medium_get_content (CAMEL_MEDIUM (content_adept
));
703 g_object_ref (orig_content
);
706 multipart
= camel_multipart_new ();
707 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart
), "multipart/mixed");
708 camel_multipart_set_boundary (multipart
, NULL
);
710 part
= camel_mime_part_new ();
711 camel_medium_set_content (CAMEL_MEDIUM (part
), CAMEL_DATA_WRAPPER (orig_content
));
712 camel_multipart_add_part (multipart
, part
);
713 g_object_unref (part
);
715 part
= camel_mime_part_new ();
716 /* Value doesn't matter, it's checked for an existence only */
717 camel_medium_add_header (CAMEL_MEDIUM (part
), E_MAIL_NOTES_HEADER
, "True");
718 camel_mime_part_set_disposition (CAMEL_MIME_PART (part
), "inline");
719 camel_mime_part_set_description (CAMEL_MIME_PART (part
), _("Message Note"));
720 camel_medium_set_content (CAMEL_MEDIUM (part
), CAMEL_DATA_WRAPPER (note
));
722 camel_mime_part_set_content_type (part
, "message/rfc822");
724 camel_multipart_add_part (multipart
, part
);
725 g_object_unref (part
);
727 camel_medium_set_content (CAMEL_MEDIUM (message
), CAMEL_DATA_WRAPPER (multipart
));
729 camel_medium_set_content (CAMEL_MEDIUM (message
), CAMEL_DATA_WRAPPER (orig_content
));
732 g_clear_object (&orig_content
);
738 action_close_cb (GtkAction
*action
,
739 EMailNotesEditor
*notes_editor
)
741 EContentEditor
*cnt_editor
;
742 gboolean something_changed
= FALSE
;
744 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
746 something_changed
= e_content_editor_get_changed (cnt_editor
);
748 if (something_changed
) {
751 response
= e_alert_run_dialog_for_args (
752 GTK_WINDOW (notes_editor
),
753 "mail:ask-mail-note-changed", NULL
);
754 if (response
== GTK_RESPONSE_YES
) {
755 GtkActionGroup
*action_group
;
757 action_group
= notes_editor
->action_group
;
758 action
= gtk_action_group_get_action (
759 action_group
, "save-and-close");
760 gtk_action_activate (action
);
762 } else if (response
== GTK_RESPONSE_CANCEL
)
766 gtk_widget_destroy (GTK_WIDGET (notes_editor
));
770 EMailNotesEditor
*notes_editor
;
771 CamelMimeMessage
*inner_message
;
776 save_and_close_data_free (gpointer ptr
)
778 SaveAndCloseData
*scd
= ptr
;
782 gtk_widget_destroy (GTK_WIDGET (scd
->notes_editor
));
784 g_clear_object (&scd
->notes_editor
);
785 g_clear_object (&scd
->inner_message
);
791 e_mail_notes_store_changes_thread (EAlertSinkThreadJobData
*job_data
,
793 GCancellable
*cancellable
,
796 CamelMimeMessage
*message
;
797 SaveAndCloseData
*scd
= user_data
;
799 g_return_if_fail (scd
!= NULL
);
801 if (g_cancellable_set_error_if_cancelled (cancellable
, error
))
804 if (!scd
->inner_message
) {
805 scd
->success
= e_mail_notes_remove_sync (scd
->notes_editor
->folder
,
806 scd
->notes_editor
->uid
, cancellable
, error
);
810 message
= camel_folder_get_message_sync (scd
->notes_editor
->folder
, scd
->notes_editor
->uid
, cancellable
, error
);
814 e_mail_notes_replace_note (message
, scd
->inner_message
);
816 scd
->success
= e_mail_notes_replace_message_in_folder_sync (scd
->notes_editor
->folder
,
817 scd
->notes_editor
->uid
, message
, TRUE
, cancellable
, error
);
819 g_clear_object (&message
);
823 action_save_and_close_cb (GtkAction
*action
,
824 EMailNotesEditor
*notes_editor
)
826 SaveAndCloseData
*scd
;
827 gchar
*full_display_name
;
828 EActivityBar
*activity_bar
;
831 g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor
));
833 scd
= g_new0 (SaveAndCloseData
, 1);
834 scd
->notes_editor
= g_object_ref (notes_editor
);
835 scd
->inner_message
= e_mail_notes_editor_encode_text_to_message (notes_editor
);
836 scd
->success
= FALSE
;
838 full_display_name
= e_mail_folder_to_full_display_name (notes_editor
->folder
, NULL
);
840 activity_bar
= e_html_editor_get_activity_bar (notes_editor
->editor
);
841 activity
= e_alert_sink_submit_thread_job (E_ALERT_SINK (notes_editor
->editor
),
842 _("Storing changes..."), "mail:failed-store-note",
843 full_display_name
? full_display_name
: camel_folder_get_display_name (notes_editor
->folder
),
844 e_mail_notes_store_changes_thread
,
845 scd
, save_and_close_data_free
);
846 e_activity_bar_set_activity (activity_bar
, activity
);
847 g_clear_object (&activity
);
849 g_free (full_display_name
);
853 e_mail_notes_editor_dispose (GObject
*object
)
855 EMailNotesEditor
*notes_editor
= E_MAIL_NOTES_EDITOR (object
);
857 if (notes_editor
->editor
) {
858 EActivityBar
*activity_bar
;
860 activity_bar
= e_html_editor_get_activity_bar (notes_editor
->editor
);
861 g_signal_handlers_disconnect_by_func (activity_bar
,
862 G_CALLBACK (notes_editor_activity_notify_cb
), notes_editor
);
864 notes_editor
->editor
= NULL
;
867 g_clear_object (¬es_editor
->focus_tracker
);
868 g_clear_object (¬es_editor
->action_group
);
870 /* Chain up to parent's method */
871 G_OBJECT_CLASS (e_mail_notes_editor_parent_class
)->dispose (object
);
875 e_mail_notes_editor_finalize (GObject
*object
)
877 EMailNotesEditor
*notes_editor
= E_MAIL_NOTES_EDITOR (object
);
879 g_clear_object (¬es_editor
->focus_tracker
);
880 g_clear_object (¬es_editor
->folder
);
881 g_clear_object (¬es_editor
->message
);
882 g_free (notes_editor
->uid
);
884 /* Chain up to parent's method */
885 G_OBJECT_CLASS (e_mail_notes_editor_parent_class
)->finalize (object
);
889 e_mail_notes_editor_class_init (EMailNotesEditorClass
*klass
)
891 GObjectClass
*object_class
;
893 object_class
= G_OBJECT_CLASS (klass
);
894 object_class
->dispose
= e_mail_notes_editor_dispose
;
895 object_class
->finalize
= e_mail_notes_editor_finalize
;
899 e_mail_notes_editor_init (EMailNotesEditor
*notes_editor
)
903 static EMailNotesEditor
*
904 e_mail_notes_editor_new_with_editor (EHTMLEditor
*html_editor
,
911 " <menubar name='main-menu'>\n"
912 " <placeholder name='pre-edit-menu'>\n"
913 " <menu action='file-menu'>\n"
914 " <menuitem action='save-and-close'/>\n"
916 " <menuitem action='close'/>\n"
920 " <toolbar name='main-toolbar'>\n"
921 " <placeholder name='pre-main-toolbar'>\n"
922 " <toolitem action='save-and-close'/>\n"
927 GtkActionEntry entries
[] = {
934 G_CALLBACK (action_close_cb
) },
938 N_("_Save and Close"),
940 N_("Save and Close"),
941 G_CALLBACK (action_save_and_close_cb
) },
951 EMailNotesEditor
*notes_editor
;
952 EContentEditor
*cnt_editor
;
953 EFocusTracker
*focus_tracker
;
954 EActivityBar
*activity_bar
;
955 GtkUIManager
*ui_manager
;
956 GtkWidget
*widget
, *content
;
957 GtkActionGroup
*action_group
;
960 GError
*local_error
= NULL
;
962 notes_editor
= g_object_new (E_TYPE_MAIL_NOTES_EDITOR
, NULL
);
964 g_object_set (G_OBJECT (notes_editor
),
965 "transient-for", parent
,
966 "destroy-with-parent", TRUE
,
967 "window-position", GTK_WIN_POS_CENTER_ON_PARENT
,
968 "title", _("Edit Message Note"),
971 gtk_window_set_default_size (GTK_WINDOW (notes_editor
), 600, 440);
973 widget
= gtk_box_new (GTK_ORIENTATION_VERTICAL
, 0);
974 gtk_container_add (GTK_CONTAINER (notes_editor
), widget
);
975 gtk_widget_show (widget
);
979 widget
= GTK_WIDGET (html_editor
);
981 notes_editor
->editor
= html_editor
;
982 cnt_editor
= e_html_editor_get_content_editor (notes_editor
->editor
);
983 ui_manager
= e_html_editor_get_ui_manager (notes_editor
->editor
);
985 /* Because we are loading from a hard-coded string, there is
986 * no chance of I/O errors. Failure here implies a malformed
987 * UI definition. Full stop. */
988 gtk_ui_manager_add_ui_from_string (ui_manager
, ui
, -1, &local_error
);
989 if (local_error
!= NULL
)
990 g_error ("%s: Failed to load built-in UI definition: %s", G_STRFUNC
, local_error
->message
);
992 action_group
= gtk_action_group_new ("notes");
993 gtk_action_group_set_translation_domain (action_group
, GETTEXT_PACKAGE
);
994 gtk_action_group_add_actions (action_group
, entries
, G_N_ELEMENTS (entries
), notes_editor
);
995 gtk_ui_manager_insert_action_group (ui_manager
, action_group
, 0);
996 notes_editor
->action_group
= g_object_ref (action_group
);
998 /* Hide page properties because it is not inherited in the mail. */
999 action
= e_html_editor_get_action (notes_editor
->editor
, "properties-page");
1000 gtk_action_set_visible (action
, FALSE
);
1002 action
= e_html_editor_get_action (notes_editor
->editor
, "context-properties-page");
1003 gtk_action_set_visible (action
, FALSE
);
1005 gtk_ui_manager_ensure_update (ui_manager
);
1007 /* Construct the window content. */
1009 widget
= e_html_editor_get_managed_widget (notes_editor
->editor
, "/main-menu");
1010 gtk_box_pack_start (GTK_BOX (content
), widget
, FALSE
, FALSE
, 0);
1011 gtk_widget_show (widget
);
1013 widget
= e_html_editor_get_managed_widget (notes_editor
->editor
, "/main-toolbar");
1014 gtk_box_pack_start (GTK_BOX (content
), widget
, FALSE
, FALSE
, 0);
1015 gtk_widget_show (widget
);
1017 widget
= GTK_WIDGET (notes_editor
->editor
);
1018 g_object_set (G_OBJECT (widget
),
1019 "halign", GTK_ALIGN_FILL
,
1021 "valign", GTK_ALIGN_FILL
,
1024 gtk_box_pack_start (GTK_BOX (content
), widget
, TRUE
, TRUE
, 0);
1025 gtk_widget_show (widget
);
1027 widget
= e_attachment_paned_new ();
1028 gtk_box_pack_start (GTK_BOX (content
), widget
, FALSE
, FALSE
, 0);
1029 notes_editor
->attachment_paned
= E_ATTACHMENT_PANED (widget
);
1030 gtk_widget_show (widget
);
1032 e_binding_bind_property (
1033 cnt_editor
, "editable",
1034 widget
, "sensitive",
1035 G_BINDING_SYNC_CREATE
);
1037 /* Configure an EFocusTracker to manage selection actions. */
1038 focus_tracker
= e_focus_tracker_new (GTK_WINDOW (notes_editor
));
1040 action
= e_html_editor_get_action (notes_editor
->editor
, "cut");
1041 e_focus_tracker_set_cut_clipboard_action (focus_tracker
, action
);
1043 action
= e_html_editor_get_action (notes_editor
->editor
, "copy");
1044 e_focus_tracker_set_copy_clipboard_action (focus_tracker
, action
);
1046 action
= e_html_editor_get_action (notes_editor
->editor
, "paste");
1047 e_focus_tracker_set_paste_clipboard_action (focus_tracker
, action
);
1049 action
= e_html_editor_get_action (notes_editor
->editor
, "select-all");
1050 e_focus_tracker_set_select_all_action (focus_tracker
, action
);
1052 notes_editor
->focus_tracker
= focus_tracker
;
1054 gtk_widget_grab_focus (GTK_WIDGET (cnt_editor
));
1056 settings
= e_util_ref_settings ("org.gnome.evolution.mail");
1057 e_content_editor_set_html_mode (
1058 cnt_editor
, g_settings_get_boolean (settings
, "composer-send-html"));
1059 g_object_unref (settings
);
1062 notes_editor
, "delete-event",
1063 G_CALLBACK (mail_notes_editor_delete_event_cb
), NULL
);
1065 activity_bar
= e_html_editor_get_activity_bar (notes_editor
->editor
);
1067 g_signal_connect (activity_bar
, "notify::activity",
1068 G_CALLBACK (notes_editor_activity_notify_cb
), notes_editor
);
1070 notes_editor
->folder
= g_object_ref (folder
);
1071 notes_editor
->uid
= g_strdup (uid
);
1072 notes_editor
->had_message
= FALSE
;
1074 return notes_editor
;
1077 typedef struct _AsyncData
{
1079 CamelFolder
*folder
;
1084 async_data_free (gpointer ptr
)
1086 AsyncData
*ad
= ptr
;
1089 g_clear_object (&ad
->parent
);
1090 g_clear_object (&ad
->folder
);
1097 e_mail_notes_editor_ready_cb (GObject
*source_object
,
1098 GAsyncResult
*result
,
1101 AsyncData
*ad
= user_data
;
1102 GtkWidget
*html_editor
;
1103 GError
*error
= NULL
;
1105 g_return_if_fail (result
!= NULL
);
1106 g_return_if_fail (ad
!= NULL
);
1108 html_editor
= e_html_editor_new_finish (result
, &error
);
1110 g_warning ("%s: Failed to create HTML editor: %s", G_STRFUNC
, error
->message
);
1111 g_clear_error (&error
);
1113 EMailNotesEditor
*notes_editor
;
1114 EActivityBar
*activity_bar
;
1115 EActivity
*activity
;
1117 notes_editor
= e_mail_notes_editor_new_with_editor (E_HTML_EDITOR (html_editor
),
1118 ad
->parent
, ad
->folder
, ad
->uid
);
1120 activity_bar
= e_html_editor_get_activity_bar (notes_editor
->editor
);
1121 activity
= e_alert_sink_submit_thread_job (E_ALERT_SINK (notes_editor
->editor
),
1122 _("Retrieving message..."), "mail:no-retrieve-message", NULL
,
1123 e_mail_notes_retrieve_message_thread
,
1124 g_object_ref (notes_editor
), e_mail_notes_retrieve_message_done
);
1125 e_activity_bar_set_activity (activity_bar
, activity
);
1126 g_clear_object (&activity
);
1128 gtk_widget_show (GTK_WIDGET (notes_editor
));
1131 async_data_free (ad
);
1135 e_mail_notes_edit (GtkWindow
*parent
,
1136 CamelFolder
*folder
,
1141 g_return_if_fail (CAMEL_IS_FOLDER (folder
));
1142 g_return_if_fail (uid
!= NULL
);
1144 ad
= g_new0 (AsyncData
, 1);
1145 ad
->parent
= parent
? g_object_ref (parent
) : NULL
;
1146 ad
->folder
= g_object_ref (folder
);
1147 ad
->uid
= g_strdup (uid
);
1149 e_html_editor_new (e_mail_notes_editor_ready_cb
, ad
);
1153 e_mail_notes_remove_sync (CamelFolder
*folder
,
1155 GCancellable
*cancellable
,
1158 CamelMimeMessage
*message
;
1161 g_return_val_if_fail (CAMEL_IS_FOLDER (folder
), FALSE
);
1162 g_return_val_if_fail (uid
!= NULL
, FALSE
);
1164 message
= camel_folder_get_message_sync (folder
, uid
, cancellable
, error
);
1168 success
= e_mail_notes_replace_note (message
, NULL
);
1170 success
= e_mail_notes_replace_message_in_folder_sync (folder
,
1171 uid
, message
, FALSE
, cancellable
, error
);
1173 /* There was no note found in the message, thus it was successfully removed */
1177 g_clear_object (&message
);