From df6f8dc010acad646b5abe591e7beefdb8cb0cb6 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Fri, 15 Oct 2010 09:39:16 +0200 Subject: Bug #587011 - Integrate remove-duplicates into evolution --- modules/mail/e-mail-shell-view-actions.c | 134 +++++++++++++++++++++++++++++++ modules/mail/e-mail-shell-view-actions.h | 2 + 2 files changed, 136 insertions(+) (limited to 'modules/mail') diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c index b62e7c1a00..fa083bf6f2 100644 --- a/modules/mail/e-mail-shell-view-actions.c +++ b/modules/mail/e-mail-shell-view-actions.c @@ -413,6 +413,133 @@ action_mail_folder_rename_cb (GtkAction *action, em_folder_tree_edit_selected (folder_tree); } +static gchar* +get_message_checksum (CamelFolder *folder, const gchar *uid) +{ + static const GChecksumType duplicate_csum = G_CHECKSUM_SHA256; + + CamelMimeMessage *msg; + GError *error = NULL; + CamelDataWrapper *content; + CamelStream *mem; + GByteArray *buffer; + gchar *digest = NULL; + + msg = camel_folder_get_message_sync (folder, uid, NULL, &error); + + if (error || !msg) { + if (error) + g_error_free (error);; + 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); + g_object_unref (msg); + + 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 +action_mail_folder_remove_duplicates (GtkAction *action, EMailShellView *mail_shell_view) +{ + EShellView *shell_view; + EShellContent *shell_content; + GtkWindow *parent; + EMailReader *reader; + MessageList *message_list; + CamelFolder *folder; + GHashTable *messages; + GPtrArray *uids, *dups; + gint i; + + shell_view = E_SHELL_VIEW (mail_shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + parent = GTK_WINDOW (e_shell_view_get_shell_window (shell_view)); + + reader = E_MAIL_READER (shell_content); + message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader)); + uids = message_list_get_uids (message_list); + folder = message_list->folder; + + messages = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); + dups = g_ptr_array_new(); + + for (i = 0; i < uids->len; i++) { + CamelMessageInfo *msg_info = camel_folder_get_message_info (folder, uids->pdata[i]); + const CamelSummaryMessageID *mid = camel_message_info_message_id (msg_info); + guint32 flags = camel_message_info_flags (msg_info); + + if (!(flags & CAMEL_MESSAGE_DELETED)) { + gchar *digest = get_message_checksum (folder, uids->pdata[i]); + + if (digest) { + if (message_is_duplicated (messages, mid->id.id, digest)) { + g_ptr_array_add (dups, uids->pdata[i]); + 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_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_name (folder), dups->len); + + if (em_utils_prompt_user (parent, NULL, "mail:ask-remove-duplicates", msg, NULL)) { + gint ii; + + 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); + em_utils_uids_free (uids); + g_ptr_array_free (dups, TRUE); +} + static void action_mail_folder_select_thread_cb (GtkAction *action, EMailShellView *mail_shell_view) @@ -1074,6 +1201,13 @@ static GtkActionEntry mail_entries[] = { N_("Change the name of this folder"), G_CALLBACK (action_mail_folder_rename_cb) }, + { "mail-folder-remove-duplicates", + NULL, + N_("Remo_ve duplicate messages"), + "", + N_("Remove all duplicate messages"), + G_CALLBACK (action_mail_folder_remove_duplicates) }, + { "mail-folder-select-thread", NULL, N_("Select Message _Thread"), diff --git a/modules/mail/e-mail-shell-view-actions.h b/modules/mail/e-mail-shell-view-actions.h index 5eb015bd47..accabc023f 100644 --- a/modules/mail/e-mail-shell-view-actions.h +++ b/modules/mail/e-mail-shell-view-actions.h @@ -85,6 +85,8 @@ E_SHELL_WINDOW_ACTION ((window), "mail-folder-rename") #define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_ALL(window) \ E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-all") +#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_REMOVE_DUPLICATES(window) \ + E_SHELL_WINDOW_ACTION ((window), "mail-folder-remove-duplicates") #define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_THREAD(window) \ E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-thread") #define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_SUBTHREAD(window) \ -- cgit v1.2.3