Commit df6f8dc0 authored by Milan Crha's avatar Milan Crha

Bug #587011 - Integrate remove-duplicates into evolution

parent b277e14a
......@@ -472,5 +472,19 @@ You can choose to ignore this folder, overwrite or append its contents, or quit.
<_primary>"Report Not Junk" Failed</_primary>
<secondary xml:space="preserve">{0}</secondary>
</error>
<error id="ask-remove-duplicates" type="question" default="GTK_RESPONSE_YES">
<_primary>Remove duplicate messages?</_primary>
<secondary>{0}</secondary>
<button stock="gtk-cancel" response="GTK_RESPONSE_CANCEL"/>
<button stock="gtk-delete" response="GTK_RESPONSE_YES"/>
</error>
<error id="info-no-remove-duplicates" type="info" default="GTK_RESPONSE_OK">
<_primary>No duplicate messages found.</_primary>
<!-- Translators: {0} is replaced with a folder name -->
<_secondary>Folder '{0}' doesn't contain any duplicate message.</_secondary>
<button stock="gtk-ok" response="GTK_RESPONSE_OK"/>
</error>
</error-list>
......@@ -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"),
......
......@@ -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) \
......
......@@ -45,6 +45,7 @@
<menuitem action='mail-folder-select-thread'/>
<menuitem action='mail-folder-select-subthread'/>
<menuitem action='mail-folder-mark-all-as-read'/>
<menuitem action='mail-folder-remove-duplicates'/>
<menuitem action='mail-folder-expunge'/>
<separator/>
<menuitem action='mail-folder-rename'/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment