aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
Diffstat (limited to 'mail')
-rw-r--r--mail/e-mail-reader-utils.c157
-rw-r--r--mail/e-mail-reader-utils.h1
-rw-r--r--mail/e-mail-reader.c154
-rw-r--r--mail/mail.error.xml5
4 files changed, 166 insertions, 151 deletions
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 16964674b0..374bed0f0e 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -34,6 +34,7 @@
#include "mail/e-mail-backend.h"
#include "mail/e-mail-browser.h"
+#include "mail/e-mail-folder-utils.h"
#include "mail/em-composer-utils.h"
#include "mail/em-format-html-print.h"
#include "mail/em-utils.h"
@@ -43,6 +44,25 @@
#include "mail/mail-vfolder.h"
#include "mail/message-list.h"
+typedef struct _AsyncContext AsyncContext;
+
+struct _AsyncContext {
+ EActivity *activity;
+ EMailReader *reader;
+};
+
+static void
+async_context_free (AsyncContext *context)
+{
+ if (context->activity != NULL)
+ g_object_unref (context->activity);
+
+ if (context->reader != NULL)
+ g_object_unref (context->reader);
+
+ g_slice_free (AsyncContext, context);
+}
+
void
e_mail_reader_activate (EMailReader *reader,
const gchar *action_name)
@@ -337,6 +357,143 @@ exit:
em_utils_uids_free (uids);
}
+static void
+mail_reader_remove_duplicates_cb (CamelFolder *folder,
+ GAsyncResult *result,
+ AsyncContext *context)
+{
+ EAlertSink *alert_sink;
+ GHashTable *duplicates;
+ GtkWindow *parent_window;
+ guint n_duplicates;
+ GError *error = NULL;
+
+ alert_sink = e_mail_reader_get_alert_sink (context->reader);
+ parent_window = e_mail_reader_get_window (context->reader);
+
+ duplicates = e_mail_folder_find_duplicate_messages_finish (
+ folder, result, &error);
+
+ /* Ignore cancellations. */
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_warn_if_fail (duplicates == NULL);
+ e_activity_set_state (context->activity, E_ACTIVITY_CANCELLED);
+ async_context_free (context);
+ g_error_free (error);
+ return;
+
+ } else if (error != NULL) {
+ g_warn_if_fail (duplicates == NULL);
+ e_alert_submit (
+ alert_sink,
+ "mail:find-duplicate-messages",
+ error->message, NULL);
+ async_context_free (context);
+ g_error_free (error);
+ return;
+ }
+
+ g_return_if_fail (duplicates != NULL);
+
+ /* Finalize the activity here so we don't leave a message in
+ * the task bar while prompting the user for confirmation. */
+ e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
+ g_object_unref (context->activity);
+ context->activity = NULL;
+
+ n_duplicates = g_hash_table_size (duplicates);
+
+ if (n_duplicates == 0) {
+ em_utils_prompt_user (
+ parent_window, NULL,
+ "mail:info-no-remove-duplicates",
+ camel_folder_get_display_name (folder), NULL);
+ } else {
+ gchar *confirmation;
+ gboolean proceed;
+
+ confirmation = g_strdup_printf (ngettext (
+ /* Translators: %s is replaced with a folder
+ * name %u with count of duplicate messages. */
+ "Folder '%s' contains %u duplicate message. "
+ "Are you sure you want to delete it?",
+ "Folder '%s' contains %u duplicate messages. "
+ "Are you sure you want to delete them?",
+ n_duplicates),
+ camel_folder_get_display_name (folder),
+ n_duplicates);
+
+ proceed = em_utils_prompt_user (
+ parent_window, NULL,
+ "mail:ask-remove-duplicates",
+ confirmation, NULL);
+
+ if (proceed) {
+ GHashTableIter iter;
+ gpointer key;
+
+ camel_folder_freeze (folder);
+
+ g_hash_table_iter_init (&iter, duplicates);
+
+ /* Mark duplicate messages for deletion. */
+ while (g_hash_table_iter_next (&iter, &key, NULL))
+ camel_folder_delete_message (folder, key);
+
+ camel_folder_thaw (folder);
+ }
+
+ g_free (confirmation);
+ }
+
+ g_hash_table_destroy (duplicates);
+
+ async_context_free (context);
+}
+
+void
+e_mail_reader_remove_duplicates (EMailReader *reader)
+{
+ AsyncContext *context;
+ GCancellable *cancellable;
+ EMailBackend *backend;
+ CamelFolder *folder;
+ GPtrArray *uids;
+
+ g_return_if_fail (E_IS_MAIL_READER (reader));
+
+ folder = e_mail_reader_get_folder (reader);
+ uids = e_mail_reader_get_selected_uids (reader);
+ g_return_if_fail (uids != NULL);
+
+ /* XXX Either e_mail_reader_get_selected_uids()
+ * or MessageList should do this itself. */
+ g_ptr_array_set_free_func (uids, (GDestroyNotify) g_free);
+
+ /* Find duplicate messages asynchronously. */
+
+ context = g_slice_new0 (AsyncContext);
+ context->activity = e_activity_new ();
+ context->reader = g_object_ref (reader);
+
+ cancellable = camel_operation_new ();
+ e_activity_set_cancellable (context->activity, cancellable);
+
+ backend = e_mail_reader_get_backend (reader);
+ e_shell_backend_add_activity (
+ E_SHELL_BACKEND (backend), context->activity);
+
+ e_mail_folder_find_duplicate_messages (
+ folder, uids, G_PRIORITY_DEFAULT,
+ cancellable, (GAsyncReadyCallback)
+ mail_reader_remove_duplicates_cb,
+ context);
+
+ g_object_unref (cancellable);
+
+ g_ptr_array_unref (uids);
+}
+
/* Helper for e_mail_reader_reply_to_message()
* XXX This function belongs in e-html-utils.c */
static gboolean
diff --git a/mail/e-mail-reader-utils.h b/mail/e-mail-reader-utils.h
index 04b46b6257..f06d4db2d4 100644
--- a/mail/e-mail-reader-utils.h
+++ b/mail/e-mail-reader-utils.h
@@ -47,6 +47,7 @@ guint e_mail_reader_mark_selected (EMailReader *reader,
guint e_mail_reader_open_selected (EMailReader *reader);
void e_mail_reader_print (EMailReader *reader,
GtkPrintOperationAction action);
+void e_mail_reader_remove_duplicates (EMailReader *reader);
void e_mail_reader_reply_to_message (EMailReader *reader,
CamelMimeMessage *message,
EMailReplyType reply_type);
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index dc163bda06..ec667765e2 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -410,159 +410,11 @@ action_mail_remove_attachments_cb (GtkAction *action, EMailReader *reader)
mail_remove_attachments (folder, uids);
}
-static gchar *
-get_message_checksum (CamelFolder *folder, CamelMimeMessage *msg)
-{
- static const GChecksumType duplicate_csum = G_CHECKSUM_SHA256;
-
- CamelDataWrapper *content;
- CamelStream *mem;
- GByteArray *buffer;
- gchar *digest = NULL;
-
- if (!msg)
- return NULL;
-
- /* get message contents */
- content = camel_medium_get_content ((CamelMedium *) msg);
- if (!content)
- return NULL;
-
- /* calculate checksum */
- mem = camel_stream_mem_new ();
- camel_data_wrapper_decode_to_stream_sync (content, mem, NULL, NULL);
-
- buffer = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (mem));
- if (buffer)
- digest = g_compute_checksum_for_data (
- duplicate_csum, buffer->data, buffer->len);
-
- g_object_unref (mem);
-
- return digest;
-}
-
-static gboolean
-message_is_duplicated (GHashTable *messages, guint64 id, gchar *digest)
-{
- gchar *hash_digest = g_hash_table_lookup (messages, &id);
-
- if (!hash_digest)
- return FALSE;
-
- return g_str_equal (digest, hash_digest);
-}
-
static void
-remove_duplicates_got_messages_cb (CamelFolder *folder,
- GPtrArray *uids,
- GPtrArray *msgs,
- gpointer data)
-{
- EMailReader *reader = data;
- GtkWindow *parent;
- GHashTable *messages;
- GPtrArray *dups;
- gint ii;
-
- g_return_if_fail (CAMEL_IS_FOLDER (folder));
- g_return_if_fail (uids != NULL);
- g_return_if_fail (msgs != NULL);
- g_return_if_fail (msgs->len <= uids->len);
- g_return_if_fail (E_IS_MAIL_READER (reader));
-
- parent = e_mail_reader_get_window (reader);
-
- messages = g_hash_table_new_full (
- g_int_hash, g_int_equal, g_free, g_free);
- dups = g_ptr_array_new ();
-
- for (ii = 0; ii < msgs->len; ii++) {
- CamelMessageInfo *msg_info;
- const CamelSummaryMessageID *mid;
- guint32 flags;
-
- msg_info = camel_folder_get_message_info (
- folder, uids->pdata[ii]);
- mid = camel_message_info_message_id (msg_info);
- flags = camel_message_info_flags (msg_info);
-
- if (!(flags & CAMEL_MESSAGE_DELETED)) {
- gchar *digest;
-
- digest = get_message_checksum (folder, msgs->pdata[ii]);
-
- if (digest != NULL) {
- if (message_is_duplicated (
- messages, mid->id.id, digest)) {
- g_ptr_array_add (dups, uids->pdata[ii]);
- g_free (digest);
- } else {
- guint64 *id;
-
- id = g_new0 (guint64, 1);
- *id = mid->id.id;
-
- g_hash_table_insert (
- messages, id, digest);
- }
- }
- }
-
- camel_message_info_free (msg_info);
- }
-
- if (dups->len == 0) {
- em_utils_prompt_user (
- parent, NULL, "mail:info-no-remove-duplicates",
- camel_folder_get_display_name (folder), NULL);
- } else {
- gchar *msg = g_strdup_printf (ngettext (
- /* Translators: %s is replaced with a folder name
- %d with count of duplicate messages. */
- "Folder '%s' contains %d duplicate message. "
- "Are you sure you want to delete it?",
- "Folder '%s' contains %d duplicate messages. "
- "Are you sure you want to delete them?",
- dups->len),
- camel_folder_get_display_name (folder), dups->len);
-
- if (em_utils_prompt_user (
- parent, NULL, "mail:ask-remove-duplicates", msg, NULL)) {
- camel_folder_freeze (folder);
- for (ii = 0; ii < dups->len; ii++)
- camel_folder_delete_message (
- folder, g_ptr_array_index (dups, ii));
- camel_folder_thaw (folder);
- }
-
- g_free (msg);
- }
-
- g_hash_table_destroy (messages);
- g_ptr_array_free (dups, TRUE);
-}
-
-static void
-action_mail_remove_duplicates (GtkAction *action, EMailReader *reader)
+action_mail_remove_duplicates (GtkAction *action,
+ EMailReader *reader)
{
- MessageList *message_list;
- CamelFolder *folder;
- GPtrArray *uids;
-
- message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
- uids = message_list_get_selected (message_list);
- folder = message_list->folder;
-
- if (!uids || uids->len <= 1) {
- if (uids)
- em_utils_uids_free (uids);
- } else {
- /* the function itself is freeing uids */
- mail_get_messages (
- folder, uids,
- remove_duplicates_got_messages_cb, reader);
- }
+ e_mail_reader_remove_duplicates (reader);
}
static void
diff --git a/mail/mail.error.xml b/mail/mail.error.xml
index 67b7e09961..df8f5f6abd 100644
--- a/mail/mail.error.xml
+++ b/mail/mail.error.xml
@@ -510,5 +510,10 @@ An mbox account will be created to preserve the old mbox folders. You can delete
<_secondary>The reported error was &quot;{0}&quot;.</_secondary>
</error>
+ <error id="find-duplicate-messages" type="warning">
+ <_primary>Failed to find duplicate messages.</_primary>
+ <_secondary>The reported error was &quot;{0}&quot;.</_secondary>
+ </error>
+
</error-list>