diff options
author | Milan Crha <mcrha@redhat.com> | 2010-11-10 20:38:22 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2010-11-10 20:38:22 +0800 |
commit | 59da2bdfdc25d148c2bc13d8fa6281f2540ba87c (patch) | |
tree | 698261cfc43fed1ea344d51e0d3d447711d1012e | |
parent | 1d8d943f67a4e52d8c574e2598f0f2d7e03e488d (diff) | |
download | gsoc2013-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.c | 193 | ||||
-rw-r--r-- | mail/mail-ops.c | 139 | ||||
-rw-r--r-- | mail/mail-ops.h | 1 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-actions.c | 134 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-actions.h | 2 | ||||
-rw-r--r-- | ui/evolution-mail-reader.ui | 2 | ||||
-rw-r--r-- | ui/evolution-mail.ui | 1 |
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'/> |