[evolution] Bug #587011 - Integrate remove-duplicates into evolution



commit df6f8dc010acad646b5abe591e7beefdb8cb0cb6
Author: Milan Crha <mcrha redhat com>
Date:   Fri Oct 15 09:39:16 2010 +0200

    Bug #587011 - Integrate remove-duplicates into evolution

 mail/mail.error.xml                      |   14 +++
 modules/mail/e-mail-shell-view-actions.c |  134 ++++++++++++++++++++++++++++++
 modules/mail/e-mail-shell-view-actions.h |    2 +
 ui/evolution-mail.ui                     |    1 +
 4 files changed, 151 insertions(+), 0 deletions(-)
---
diff --git a/mail/mail.error.xml b/mail/mail.error.xml
index dbbb84d..60e4d56 100644
--- a/mail/mail.error.xml
+++ b/mail/mail.error.xml
@@ -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>
 
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index b62e7c1..fa083bf 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 5eb015b..accabc0 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) \
diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui
index d158cf8..4589dc6 100644
--- a/ui/evolution-mail.ui
+++ b/ui/evolution-mail.ui
@@ -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'/>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]