aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2010-11-10 20:38:22 +0800
committerMilan Crha <mcrha@redhat.com>2010-11-10 20:38:22 +0800
commit59da2bdfdc25d148c2bc13d8fa6281f2540ba87c (patch)
tree698261cfc43fed1ea344d51e0d3d447711d1012e
parent1d8d943f67a4e52d8c574e2598f0f2d7e03e488d (diff)
downloadgsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.tar
gsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.tar.gz
gsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.tar.bz2
gsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.tar.lz
gsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.tar.xz
gsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.tar.zst
gsoc2013-evolution-59da2bdfdc25d148c2bc13d8fa6281f2540ba87c.zip
Bug #632683 - Remove-duplicates should work on selection
-rw-r--r--mail/e-mail-reader.c193
-rw-r--r--mail/mail-ops.c139
-rw-r--r--mail/mail-ops.h1
-rw-r--r--modules/mail/e-mail-shell-view-actions.c134
-rw-r--r--modules/mail/e-mail-shell-view-actions.h2
-rw-r--r--ui/evolution-mail-reader.ui2
-rw-r--r--ui/evolution-mail.ui1
7 files changed, 278 insertions, 194 deletions
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index 2c1bbb2fc8..0649a43d2f 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -406,81 +406,144 @@ action_mail_remove_attachments_cb (GtkAction *action, EMailReader *reader)
{
CamelFolder *folder;
GPtrArray *uids;
- gint i, j;
folder = e_mail_reader_get_folder (reader);
uids = e_mail_reader_get_selected_uids (reader);
- camel_folder_freeze (folder);
- for (i = 0; i < (uids ? uids->len : 0); i++) {
- CamelMimeMessage *message;
- CamelDataWrapper *containee;
- gchar *uid;
+ mail_remove_attachments (folder, uids);
+}
- uid = g_ptr_array_index (uids, i);
+static gchar *
+get_message_checksum (CamelFolder *folder, CamelMimeMessage *msg)
+{
+ static const GChecksumType duplicate_csum = G_CHECKSUM_SHA256;
- /* retrieve the message from the CamelFolder */
- message = camel_folder_get_message_sync (folder, uid, NULL, NULL);
- if (!message) {
- continue;
- }
+ CamelDataWrapper *content;
+ CamelStream *mem;
+ GByteArray *buffer;
+ gchar *digest = NULL;
- containee = camel_medium_get_content (CAMEL_MEDIUM (message));
- if (containee == NULL) {
- continue;
- }
+ if (!msg)
+ return NULL;
- if (CAMEL_IS_MULTIPART (containee)) {
- gboolean deleted = FALSE;
- gint parts;
-
- parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
- for (j = 0; j < parts; j++) {
- CamelMimePart *mpart = camel_multipart_get_part (CAMEL_MULTIPART (containee), j);
- const gchar *disposition = camel_mime_part_get_disposition (mpart);
- if (disposition && (!strcmp (disposition, "attachment") || !strcmp (disposition, "inline"))) {
- gchar *desc;
- const gchar *filename;
-
- filename = camel_mime_part_get_filename (mpart);
- desc = g_strdup_printf (_("File \"%s\" has been removed."), filename ? filename : "");
- camel_mime_part_set_disposition (mpart, "inline");
- camel_mime_part_set_content (mpart, desc, strlen (desc), "text/plain");
- camel_mime_part_set_content_type (mpart, "text/plain");
- deleted = TRUE;
- }
- }
+ /* get message contents */
+ content = camel_medium_get_content ((CamelMedium *) msg);
+ if (!content)
+ return NULL;
- if (deleted) {
- /* copy the original message with the deleted attachment */
- CamelMessageInfo *info, *newinfo;
- guint32 flags;
- GError *error = NULL;
+ /* calculate checksum */
+ mem = camel_stream_mem_new ();
+ camel_data_wrapper_decode_to_stream_sync (content, mem, NULL, NULL);
- info = camel_folder_get_message_info (folder, uid);
- newinfo = camel_message_info_new_from_header (NULL, CAMEL_MIME_PART (message)->headers);
- flags = camel_folder_get_message_flags (folder, uid);
+ 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);
- /* make a copy of the message */
- camel_message_info_set_flags (newinfo, flags, flags);
- camel_folder_append_message_sync (folder, message, newinfo, NULL, NULL, &error);
+ g_object_unref (mem);
- if (!error) {
- /* marked the original message deleted */
- camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
- }
+ 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 (folder != NULL);
+ 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 (reader != NULL);
+ 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 = camel_folder_get_message_info (folder, uids->pdata[ii]);
+ const CamelSummaryMessageID *mid = camel_message_info_message_id (msg_info);
+ guint32 flags = camel_message_info_flags (msg_info);
- camel_folder_free_message_info (folder, info);
- camel_message_info_free (newinfo);
+ if (!(flags & CAMEL_MESSAGE_DELETED)) {
+ gchar *digest = get_message_checksum (folder, msgs->pdata[ii]);
- if (error)
- g_error_free (error);
+ if (digest) {
+ 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);
}
- camel_folder_synchronize_sync (folder, FALSE, NULL, NULL);
- camel_folder_thaw (folder);
+ 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)) {
+ 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)
+{
+ 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);
+ }
}
static void
@@ -2107,6 +2170,13 @@ static GtkActionEntry mail_reader_entries[] = {
N_("Remove attachments"),
G_CALLBACK (action_mail_remove_attachments_cb) },
+ { "mail-remove-duplicates",
+ NULL,
+ N_("Remove Du_plicate Messages"),
+ NULL,
+ N_("Checks selected messages for duplicates"),
+ G_CALLBACK (action_mail_remove_duplicates) },
+
{ "mail-reply-all",
NULL,
N_("Reply to _All"),
@@ -2330,6 +2400,10 @@ static EPopupActionEntry mail_reader_popup_entries[] = {
NULL,
"mail-remove-attachments" },
+ { "mail-popup-remove-duplicates",
+ NULL,
+ "mail-remove-duplicates" },
+
{ "mail-popup-reply-all",
NULL,
"mail-reply-all" },
@@ -3165,6 +3239,11 @@ mail_reader_update_actions (EMailReader *reader,
action = e_mail_reader_get_action (reader, action_name);
gtk_action_set_sensitive (action, sensitive);
+ action_name = "mail-remove-duplicates";
+ sensitive = multiple_messages_selected;
+ action = e_mail_reader_get_action (reader, action_name);
+ gtk_action_set_sensitive (action, sensitive);
+
action_name = "mail-reply-all";
sensitive = have_enabled_account && single_message_selected;
action = e_mail_reader_get_action (reader, action_name);
diff --git a/mail/mail-ops.c b/mail/mail-ops.c
index 24826afd10..28cd77a613 100644
--- a/mail/mail-ops.c
+++ b/mail/mail-ops.c
@@ -2599,3 +2599,142 @@ mail_disconnect_store (CamelStore *store)
return id;
}
+
+/* ---------------------------------------------------------------------------------- */
+
+struct _remove_attachments_msg {
+ MailMsg base;
+
+ CamelFolder *folder;
+ GPtrArray *uids;
+};
+
+static gchar *
+remove_attachments_desc (struct _remove_attachments_msg *m)
+{
+ return g_strdup_printf (_("Removing attachments"));
+}
+
+static void
+remove_attachments_exec (struct _remove_attachments_msg *m,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelFolder *folder = m->folder;
+ GPtrArray *uids = m->uids;
+ gint ii, jj;
+
+ camel_folder_freeze (folder);
+ for (ii = 0; ii < (uids ? uids->len : 0); ii++) {
+ gint pc = ((ii + 1) * 100) / uids->len;
+ CamelMimeMessage *message;
+ CamelDataWrapper *containee;
+ gchar *uid;
+
+ uid = g_ptr_array_index (uids, ii);
+
+ /* retrieve the message from the CamelFolder */
+ message = camel_folder_get_message_sync (folder, uid, cancellable, NULL);
+ if (!message) {
+ camel_operation_progress (cancellable, pc);
+ continue;
+ }
+
+ containee = camel_medium_get_content (CAMEL_MEDIUM (message));
+ if (containee == NULL) {
+ camel_operation_progress (cancellable, pc);
+ continue;
+ }
+
+ if (CAMEL_IS_MULTIPART (containee)) {
+ gboolean deleted = FALSE;
+ gint parts;
+
+ parts = camel_multipart_get_number (CAMEL_MULTIPART (containee));
+ for (jj = 0; jj < parts; jj++) {
+ CamelMimePart *mpart = camel_multipart_get_part (CAMEL_MULTIPART (containee), jj);
+ const gchar *disposition = camel_mime_part_get_disposition (mpart);
+ if (disposition && (!strcmp (disposition, "attachment") || !strcmp (disposition, "inline"))) {
+ gchar *desc;
+ const gchar *filename;
+
+ filename = camel_mime_part_get_filename (mpart);
+ desc = g_strdup_printf (_("File \"%s\" has been removed."), filename ? filename : "");
+ camel_mime_part_set_disposition (mpart, "inline");
+ camel_mime_part_set_content (mpart, desc, strlen (desc), "text/plain");
+ camel_mime_part_set_content_type (mpart, "text/plain");
+ deleted = TRUE;
+ }
+ }
+
+ if (deleted) {
+ /* copy the original message with the deleted attachment */
+ CamelMessageInfo *info, *newinfo;
+ guint32 flags;
+ GError *local_error = NULL;
+
+ info = camel_folder_get_message_info (folder, uid);
+ newinfo = camel_message_info_new_from_header (NULL, CAMEL_MIME_PART (message)->headers);
+ flags = camel_folder_get_message_flags (folder, uid);
+
+ /* make a copy of the message */
+ camel_message_info_set_flags (newinfo, flags, flags);
+ camel_folder_append_message_sync (folder, message, newinfo, NULL, cancellable, &local_error);
+
+ if (!local_error) {
+ /* marked the original message deleted */
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
+ }
+
+ camel_folder_free_message_info (folder, info);
+ camel_message_info_free (newinfo);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ break;
+ }
+ }
+ }
+
+ camel_operation_progress (cancellable, pc);
+ }
+
+ if (!error || !*error)
+ camel_folder_synchronize_sync (folder, FALSE, cancellable, error);
+ camel_folder_thaw (folder);
+}
+
+static void
+remove_attachments_free (struct _remove_attachments_msg *m)
+{
+ g_object_unref (m->folder);
+ em_utils_uids_free (m->uids);
+}
+
+static MailMsgInfo remove_attachments_info = {
+ sizeof (struct _remove_attachments_msg),
+ (MailMsgDescFunc) remove_attachments_desc,
+ (MailMsgExecFunc) remove_attachments_exec,
+ (MailMsgDoneFunc) NULL,
+ (MailMsgFreeFunc) remove_attachments_free
+};
+
+/* it takes ownership of 'uids' array */
+gint
+mail_remove_attachments (CamelFolder *folder, GPtrArray *uids)
+{
+ struct _remove_attachments_msg *m;
+ gint id;
+
+ g_return_val_if_fail (folder != NULL, -1);
+ g_return_val_if_fail (uids != NULL, -1);
+
+ m = mail_msg_new (&remove_attachments_info);
+ m->folder = g_object_ref (folder);
+ m->uids = uids;
+
+ id = m->base.seq;
+ mail_msg_unordered_push (m);
+
+ return id;
+}
diff --git a/mail/mail-ops.h b/mail/mail-ops.h
index 77ce991d5f..98f9125ff7 100644
--- a/mail/mail-ops.h
+++ b/mail/mail-ops.h
@@ -164,6 +164,7 @@ gint mail_check_service (EMailSession *session,
gpointer data);
gint mail_disconnect_store (CamelStore *store);
+gint mail_remove_attachments (CamelFolder *folder, GPtrArray *uids);
G_END_DECLS
diff --git a/modules/mail/e-mail-shell-view-actions.c b/modules/mail/e-mail-shell-view-actions.c
index 0c82778f5e..b2c5b8d1bb 100644
--- a/modules/mail/e-mail-shell-view-actions.c
+++ b/modules/mail/e-mail-shell-view-actions.c
@@ -447,133 +447,6 @@ 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)
@@ -1249,13 +1122,6 @@ 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 accabc023f..5eb015bd47 100644
--- a/modules/mail/e-mail-shell-view-actions.h
+++ b/modules/mail/e-mail-shell-view-actions.h
@@ -85,8 +85,6 @@
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-reader.ui b/ui/evolution-mail-reader.ui
index 712014783c..ffc16a980d 100644
--- a/ui/evolution-mail-reader.ui
+++ b/ui/evolution-mail-reader.ui
@@ -97,6 +97,7 @@
<menuitem action='mail-filters-apply'/>
<menuitem action='mail-check-for-junk'/>
<menuitem action='mail-remove-attachments'/>
+ <menuitem action='mail-remove-duplicates'/>
<separator/>
<menu action='mail-create-rule-menu'>
<menuitem action='mail-filter-on-subject'/>
@@ -159,6 +160,7 @@
<menuitem action='mail-popup-save-as'/>
<menuitem action='mail-popup-print'/>
<menuitem action='mail-popup-remove-attachments'/>
+ <menuitem action='mail-popup-remove-duplicates'/>
</placeholder>
</popup>
<popup name='mail-preview-popup'>
diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui
index 4589dc6b46..d158cf862b 100644
--- a/ui/evolution-mail.ui
+++ b/ui/evolution-mail.ui
@@ -45,7 +45,6 @@
<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'/>