diff options
Diffstat (limited to 'mail/em-composer-utils.c')
-rw-r--r-- | mail/em-composer-utils.c | 348 |
1 files changed, 230 insertions, 118 deletions
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c index 7bb87222cd..4b1d9aedce 100644 --- a/mail/em-composer-utils.c +++ b/mail/em-composer-utils.c @@ -37,20 +37,22 @@ #include "mail-config.h" #include "mail-session.h" #include "mail-send-recv.h" -#include "mail-component.h" #include "e-util/e-error.h" +#include "e-util/e-account-utils.h" #include "em-utils.h" #include "em-composer-utils.h" #include "composer/e-msg-composer.h" #include "composer/e-composer-autosave.h" +#include "composer/e-composer-post-header.h" +#include "em-folder-selector.h" +#include "em-folder-tree.h" #include "em-format-html.h" +#include "em-format-html-print.h" #include "em-format-quote.h" #include "em-event.h" -#include "libedataserver/e-account-list.h" - #include <camel/camel-folder.h> #include <camel/camel-multipart.h> #include <camel/camel-string-utils.h> @@ -58,6 +60,8 @@ #include <camel/camel-nntp-address.h> #include <camel/camel-vee-folder.h> +#include "e-mail-shell-backend.h" + #ifdef G_OS_WIN32 /* Undef the similar macro from pthread.h, it doesn't check if * gmtime() returns NULL. @@ -72,6 +76,9 @@ static EAccount * guess_account (CamelMimeMessage *message, CamelFolder *folder); +static void em_utils_composer_send_cb (EMsgComposer *composer); +static void em_utils_composer_save_draft_cb (EMsgComposer *composer); + struct emcs_t { guint ref_count; @@ -88,28 +95,63 @@ emcs_new (void) { struct emcs_t *emcs; - emcs = g_new (struct emcs_t, 1); + emcs = g_new0 (struct emcs_t, 1); emcs->ref_count = 1; - emcs->drafts_folder = NULL; - emcs->drafts_uid = NULL; - emcs->folder = NULL; - emcs->flags = 0; - emcs->set = 0; - emcs->uid = NULL; return emcs; } static void +emcs_set_drafts_info (struct emcs_t *emcs, + CamelFolder *drafts_folder, + const gchar *drafts_uid) +{ + g_return_if_fail (emcs != NULL); + g_return_if_fail (drafts_folder != NULL); + g_return_if_fail (drafts_uid != NULL); + + if (emcs->drafts_folder != NULL) + camel_object_unref (emcs->drafts_folder); + g_free (emcs->drafts_uid); + + camel_object_ref (drafts_folder); + emcs->drafts_folder = drafts_folder; + emcs->drafts_uid = g_strdup (drafts_uid); +} + +static void +emcs_set_folder_info (struct emcs_t *emcs, + CamelFolder *folder, + const gchar *uid, + guint32 flags, + guint32 set) +{ + g_return_if_fail (emcs != NULL); + g_return_if_fail (folder != NULL); + g_return_if_fail (uid != NULL); + + if (emcs->folder != NULL) + camel_object_unref (emcs->folder); + g_free (emcs->uid); + + camel_object_ref (folder); + emcs->folder = folder; + emcs->uid = g_strdup (uid); + emcs->flags = flags; + emcs->set = set; +} + +static void free_emcs (struct emcs_t *emcs) { - if (emcs->drafts_folder) + if (emcs->drafts_folder != NULL) camel_object_unref (emcs->drafts_folder); g_free (emcs->drafts_uid); - if (emcs->folder) + if (emcs->folder != NULL) camel_object_unref (emcs->folder); g_free (emcs->uid); + g_free (emcs); } @@ -127,12 +169,6 @@ emcs_unref (struct emcs_t *emcs) free_emcs (emcs); } -static void -composer_destroy_cb (gpointer user_data, GObject *deadbeef) -{ - emcs_unref (user_data); -} - static gboolean ask_confirm_for_unwanted_html_mail (EMsgComposer *composer, EDestination **recipients) { @@ -226,17 +262,6 @@ composer_send_queued_cb (CamelFolder *folder, CamelMimeMessage *msg, CamelMessag mail_send (); } } else { - if (!emcs) { - /* disconnect the previous signal handlers */ - g_signal_handlers_disconnect_matched (send->composer, G_SIGNAL_MATCH_FUNC, 0, - 0, NULL, em_utils_composer_send_cb, NULL); - g_signal_handlers_disconnect_matched (send->composer, G_SIGNAL_MATCH_FUNC, 0, - 0, NULL, em_utils_composer_save_draft_cb, NULL); - - /* reconnect to the signals using a non-NULL emcs for the callback data */ - em_composer_utils_setup_default_callbacks (send->composer); - } - e_msg_composer_set_enable_autosave (send->composer, TRUE); gtk_widget_show (GTK_WIDGET (send->composer)); } @@ -416,8 +441,8 @@ composer_get_message (EMsgComposer *composer, gboolean save_html_object_data) return message; } -void -em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) +static void +em_utils_composer_send_cb (EMsgComposer *composer) { EComposerHeaderTable *table; CamelMimeMessage *message; @@ -429,32 +454,36 @@ em_utils_composer_send_cb (EMsgComposer *composer, gpointer user_data) table = e_msg_composer_get_header_table (composer); account = e_composer_header_table_get_account (table); if (!account || !account->enabled) { - e_error_run((GtkWindow *)composer, "mail:send-no-account-enabled", NULL); + e_error_run ( + GTK_WINDOW (composer), + "mail:send-no-account-enabled", NULL); return; } - if (!(message = composer_get_message (composer, FALSE))) + if ((message = composer_get_message (composer, FALSE)) == NULL) return; - mail_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + mail_folder = e_mail_shell_backend_get_folder ( + global_mail_shell_backend, E_MAIL_FOLDER_OUTBOX); camel_object_ref (mail_folder); /* mail the message */ - info = camel_message_info_new(NULL); - camel_message_info_set_flags(info, CAMEL_MESSAGE_SEEN, ~0); + info = camel_message_info_new (NULL); + camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, ~0); send = g_malloc (sizeof (*send)); - send->emcs = user_data; + send->emcs = g_object_get_data (G_OBJECT (composer), "emcs"); if (send->emcs) emcs_ref (send->emcs); send->send = TRUE; - send->composer = composer; - g_object_ref (composer); + send->composer = g_object_ref (composer); gtk_widget_hide (GTK_WIDGET (composer)); e_msg_composer_set_enable_autosave (composer, FALSE); - mail_append_mail (mail_folder, message, info, composer_send_queued_cb, send); + mail_append_mail ( + mail_folder, message, info, composer_send_queued_cb, send); + camel_object_unref (mail_folder); camel_object_unref (message); } @@ -495,17 +524,9 @@ save_draft_done (CamelFolder *folder, CamelMimeMessage *msg, CamelMessageInfo *i composer_set_no_change (sdi->composer, FALSE, FALSE); - if ((emcs = sdi->emcs) == NULL) { + if ((emcs = sdi->emcs) == NULL) emcs = emcs_new (); - /* disconnect the previous signal handlers */ - g_signal_handlers_disconnect_by_func (sdi->composer, G_CALLBACK (em_utils_composer_send_cb), NULL); - g_signal_handlers_disconnect_by_func (sdi->composer, G_CALLBACK (em_utils_composer_save_draft_cb), NULL); - - /* reconnect to the signals using a non-NULL emcs for the callback data */ - em_composer_utils_setup_default_callbacks (sdi->composer); - } - if (emcs->drafts_folder) { /* delete the original draft message */ camel_folder_set_message_flags (emcs->drafts_folder, emcs->drafts_uid, @@ -557,13 +578,13 @@ save_draft_folder (gchar *uri, CamelFolder *folder, gpointer data) } } -void -em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) +static void +em_utils_composer_save_draft_cb (EMsgComposer *composer) { - const gchar *default_drafts_folder_uri = mail_component_get_folder_uri(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); - CamelFolder *drafts_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_DRAFTS); + CamelFolder *local_drafts_folder; EComposerHeaderTable *table; struct _save_draft_info *sdi; + const gchar *local_drafts_folder_uri; CamelFolder *folder = NULL; CamelMimeMessage *msg; CamelMessageInfo *info; @@ -573,19 +594,25 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) * get destroyed while we're in mail_msg_wait() a little lower * down, waiting for the folder to open */ - g_object_ref(composer); + local_drafts_folder = e_mail_shell_backend_get_folder ( + global_mail_shell_backend, E_MAIL_FOLDER_DRAFTS); + + local_drafts_folder_uri = e_mail_shell_backend_get_folder_uri ( + global_mail_shell_backend, E_MAIL_FOLDER_DRAFTS); + + g_object_ref (composer); msg = e_msg_composer_get_message_draft (composer); table = e_msg_composer_get_header_table (composer); account = e_composer_header_table_get_account (table); - sdi = g_malloc(sizeof(struct _save_draft_info)); + sdi = g_malloc (sizeof(struct _save_draft_info)); sdi->composer = composer; - sdi->emcs = user_data; + sdi->emcs = g_object_get_data (G_OBJECT (composer), "emcs"); if (sdi->emcs) - emcs_ref(sdi->emcs); + emcs_ref (sdi->emcs); if (account && account->drafts_folder_uri && - strcmp (account->drafts_folder_uri, default_drafts_folder_uri) != 0) { + strcmp (account->drafts_folder_uri, local_drafts_folder_uri) != 0) { gint id; id = mail_get_folder (account->drafts_folder_uri, 0, save_draft_folder, &folder, mail_msg_unordered_push); @@ -601,11 +628,11 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) return; } - folder = drafts_folder; - camel_object_ref (drafts_folder); + folder = local_drafts_folder; + camel_object_ref (local_drafts_folder); } } else { - folder = drafts_folder; + folder = local_drafts_folder; camel_object_ref (folder); } @@ -617,43 +644,24 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer, gpointer user_data) camel_object_unref (msg); } -void -em_composer_utils_setup_callbacks (EMsgComposer *composer, - CamelFolder *folder, - const gchar *uid, - guint32 flags, - guint32 set, - CamelFolder *drafts, - const gchar *drafts_uid) +static void +em_utils_composer_print_cb (EMsgComposer *composer, + GtkPrintOperationAction action) { - struct emcs_t *emcs; - - emcs = emcs_new (); - - if (folder && uid) { - camel_object_ref (folder); - emcs->folder = folder; - emcs->uid = g_strdup (uid); - emcs->flags = flags; - emcs->set = set; - } - - if (drafts && drafts_uid) { - camel_object_ref (drafts); - emcs->drafts_folder = drafts; - emcs->drafts_uid = g_strdup (drafts_uid); - } + CamelMimeMessage *message; + EMFormatHTMLPrint *efhp; - g_signal_connect (composer, "send", G_CALLBACK (em_utils_composer_send_cb), emcs); - g_signal_connect (composer, "save-draft", G_CALLBACK (em_utils_composer_save_draft_cb), emcs); + message = e_msg_composer_get_message_print (composer, 1); - g_object_weak_ref ((GObject *) composer, (GWeakNotify) composer_destroy_cb, emcs); + efhp = em_format_html_print_new (NULL, action); + em_format_html_print_raw_message (efhp, message); + g_object_unref (efhp); } /* Composing messages... */ static EMsgComposer * -create_new_composer (const gchar *subject, const gchar *fromuri, gboolean use_default_callbacks, gboolean lite) +create_new_composer (const gchar *subject, const gchar *fromuri, gboolean lite) { EMsgComposer *composer; EComposerHeaderTable *table; @@ -678,9 +686,6 @@ create_new_composer (const gchar *subject, const gchar *fromuri, gboolean use_de e_composer_header_table_set_account (table, account); e_composer_header_table_set_subject (table, subject); - if (use_default_callbacks) - em_composer_utils_setup_default_callbacks (composer); - return composer; } @@ -695,7 +700,7 @@ em_utils_compose_new_message (const gchar *fromuri) { GtkWidget *composer; - composer = (GtkWidget *) create_new_composer ("", fromuri, TRUE, FALSE); + composer = (GtkWidget *) create_new_composer ("", fromuri, FALSE); if (composer == NULL) return; @@ -715,7 +720,7 @@ em_utils_compose_lite_new_message (const gchar *fromuri) { GtkWidget *composer; - composer = (GtkWidget *) create_new_composer ("", fromuri, TRUE, TRUE); + composer = (GtkWidget *) create_new_composer ("", fromuri, TRUE); if (composer == NULL) return NULL; @@ -732,7 +737,7 @@ em_utils_compose_lite_new_message (const gchar *fromuri) * window. If @url is non-NULL, the composer fields will be filled in * according to the values in the mailto url. **/ -struct _EMsgComposer * +void em_utils_compose_new_message_with_mailto (const gchar *url, const gchar *fromuri) { EMsgComposer *composer; @@ -745,7 +750,6 @@ em_utils_compose_new_message_with_mailto (const gchar *url, const gchar *fromuri composer = e_msg_composer_new (); table = e_msg_composer_get_header_table (composer); - em_composer_utils_setup_default_callbacks (composer); if (fromuri && (account = mail_config_get_account_by_source_url(fromuri))) @@ -753,12 +757,8 @@ em_utils_compose_new_message_with_mailto (const gchar *url, const gchar *fromuri composer_set_no_change (composer, TRUE, url == NULL); - if (!e_msg_composer_get_lite()) { - gtk_widget_show ((GtkWidget *) composer); - gdk_window_raise (((GtkWidget *) composer)->window); - } - - return composer; + gtk_widget_show ((GtkWidget *) composer); + gdk_window_raise (((GtkWidget *) composer)->window); } /* Editing messages... */ @@ -903,10 +903,12 @@ edit_message (CamelMimeMessage *message, CamelFolder *drafts, const gchar *uid) composer = e_msg_composer_new_with_message (message); - if (em_utils_folder_is_templates(drafts, NULL) == TRUE) - em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, NULL, NULL); - else - em_composer_utils_setup_callbacks (composer, NULL, NULL, 0, 0, drafts, uid); + if (em_utils_folder_is_drafts (drafts, NULL)) { + struct emcs_t *emcs; + + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_drafts_info (emcs, drafts, uid); + } composer_set_no_change (composer, TRUE, FALSE); @@ -1029,7 +1031,7 @@ forward_attached (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, Cam { EMsgComposer *composer; - composer = create_new_composer (subject, fromuri, TRUE, FALSE); + composer = create_new_composer (subject, fromuri, FALSE); if (composer == NULL) return; @@ -1108,7 +1110,7 @@ forward_non_attached (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, text = em_utils_message_to_html (message, _("-------- Forwarded Message --------"), flags, &len, NULL, NULL); if (text) { - composer = create_new_composer (subject, fromuri, !uids || !uids->pdata [i], FALSE); + composer = create_new_composer (subject, fromuri, FALSE); if (composer) { if (CAMEL_IS_MULTIPART(camel_medium_get_content_object((CamelMedium *)message))) @@ -1116,8 +1118,12 @@ forward_non_attached (CamelFolder *folder, GPtrArray *uids, GPtrArray *messages, e_msg_composer_set_body_text (composer, text, len); - if (uids && uids->pdata[i]) - em_composer_utils_setup_callbacks (composer, folder, uids->pdata[i], CAMEL_MESSAGE_FORWARDED, CAMEL_MESSAGE_FORWARDED, NULL, NULL); + if (uids && uids->pdata[i]) { + struct emcs_t *emcs; + + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_folder_info (emcs, folder, uids->pdata[i], CAMEL_MESSAGE_FORWARDED, CAMEL_MESSAGE_FORWARDED); + } composer_set_no_change (composer, TRUE, FALSE); @@ -1273,8 +1279,6 @@ redirect_get_composer (CamelMimeMessage *message) composer = e_msg_composer_new_redirect (message, account ? account->name : NULL); - em_composer_utils_setup_default_callbacks (composer); - return composer; } @@ -1517,7 +1521,8 @@ em_utils_send_receipt (CamelFolder *folder, CamelMimeMessage *message) } /* Send the receipt */ - out_folder = mail_component_get_folder(NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + out_folder = e_mail_shell_backend_get_folder ( + global_mail_shell_backend, E_MAIL_FOLDER_OUTBOX); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); mail_append_mail (out_folder, receipt, info, em_utils_receipt_done, NULL); @@ -1613,7 +1618,8 @@ em_utils_forward_message_raw (CamelFolder *folder, CamelMimeMessage *message, co g_free (subject); /* and send it */ - out_folder = mail_component_get_folder (NULL, MAIL_COMPONENT_FOLDER_OUTBOX); + out_folder = e_mail_shell_backend_get_folder ( + global_mail_shell_backend, E_MAIL_FOLDER_OUTBOX); info = camel_message_info_new (NULL); camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN); mail_append_mail (out_folder, forward, info, emu_forward_raw_done, NULL); @@ -1629,10 +1635,10 @@ generate_account_hash (void) EAccountList *accounts; EIterator *iter; - accounts = mail_config_get_accounts (); + accounts = e_get_account_list (); account_hash = g_hash_table_new (camel_strcase_hash, camel_strcase_equal); - def = mail_config_get_default_account (); + def = e_get_default_account (); iter = e_list_get_iterator ((EList *) accounts); while (e_iterator_is_valid (iter)) { @@ -2314,6 +2320,7 @@ em_utils_reply_to_message(CamelFolder *folder, const gchar *uid, CamelMimeMessag guint32 flags; EMEvent *eme; EMEventTargetMessage *target; + struct emcs_t *emcs; if (folder && uid && message == NULL) { struct _reply_data *rd = g_malloc0(sizeof(*rd)); @@ -2378,7 +2385,8 @@ em_utils_reply_to_message(CamelFolder *folder, const gchar *uid, CamelMimeMessag composer_set_body (composer, message, source); - em_composer_utils_setup_callbacks (composer, folder, uid, flags, flags, NULL, NULL); + emcs = g_object_get_data (G_OBJECT (composer), "emcs"); + emcs_set_folder_info (emcs, folder, uid, flags, flags); composer_set_no_change (composer, TRUE, FALSE); @@ -2387,3 +2395,107 @@ em_utils_reply_to_message(CamelFolder *folder, const gchar *uid, CamelMimeMessag return composer; } + +static void +post_header_clicked_cb (EComposerPostHeader *header, + EMailShellBackend *mail_shell_backend) +{ + EMFolderTreeModel *model; + GtkWidget *folder_tree; + GtkWidget *dialog; + GList *list; + + model = e_mail_shell_backend_get_folder_tree_model (mail_shell_backend); + folder_tree = em_folder_tree_new_with_model (model); + + em_folder_tree_set_multiselect (EM_FOLDER_TREE (folder_tree), TRUE); + + em_folder_tree_set_excluded ( + EM_FOLDER_TREE (folder_tree), + EMFT_EXCLUDE_NOSELECT | + EMFT_EXCLUDE_VIRTUAL | + EMFT_EXCLUDE_VTRASH); + + dialog = em_folder_selector_new ( + EM_FOLDER_TREE (folder_tree), + EM_FOLDER_SELECTOR_CAN_CREATE, + _("Posting destination"), + _("Choose folders to post the message to."), + NULL); + + list = e_composer_post_header_get_folders (header); + em_folder_selector_set_selected_list ( + EM_FOLDER_SELECTOR (dialog), list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) { + /* Prevent the header's "custom" flag from being reset, + * which is what the default method will do next. */ + g_signal_stop_emission_by_name (header, "clicked"); + goto exit; + } + + list = em_folder_selector_get_selected_uris ( + EM_FOLDER_SELECTOR (dialog)); + e_composer_post_header_set_folders (header, list); + g_list_foreach (list, (GFunc) g_free, NULL); + g_list_free (list); + +exit: + gtk_widget_destroy (dialog); +} + +/** + * em_configure_new_composer: + * @composer: a newly created #EMsgComposer + * + * Integrates a newly created #EMsgComposer into the mail backend. The + * composer can't link directly to the mail backend without introducing + * circular library dependencies, so this function finishes configuring + * things the #EMsgComposer instance can't do itself. + **/ +void +em_configure_new_composer (EMsgComposer *composer) +{ + EComposerHeaderTable *table; + EComposerHeaderType header_type; + EComposerHeader *header; + struct emcs_t *emcs; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + + header_type = E_COMPOSER_HEADER_POST_TO; + table = e_msg_composer_get_header_table (composer); + header = e_composer_header_table_get_header (table, header_type); + + emcs = emcs_new (); + + g_object_set_data_full ( + G_OBJECT (composer), "emcs", emcs, + (GDestroyNotify) emcs_unref); + + g_signal_connect ( + composer, "send", + G_CALLBACK (em_utils_composer_send_cb), NULL); + + g_signal_connect ( + composer, "save-draft", + G_CALLBACK (em_utils_composer_save_draft_cb), NULL); + + g_signal_connect ( + composer, "print", + G_CALLBACK (em_utils_composer_print_cb), NULL); + + /* Handle "Post To:" button clicks, which displays a folder tree + * widget. The composer doesn't know about folder tree widgets, + * so it can't handle this itself. + * + * Note: This is a G_SIGNAL_RUN_LAST signal, which allows us to + * stop the signal emission if the user cancels or closes + * the folder selector dialog. See the handler function. */ + g_signal_connect ( + header, "clicked", + G_CALLBACK (post_header_clicked_cb), + global_mail_shell_backend); +} |