[evolution] Bug 300871 - Ignore a specific thread
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug 300871 - Ignore a specific thread
- Date: Mon, 27 Oct 2014 21:27:02 +0000 (UTC)
commit 4a8c3fa737a35331136a58be9caee19774dc8fdb
Author: Milan Crha <mcrha redhat com>
Date: Mon Oct 27 22:26:29 2014 +0100
Bug 300871 - Ignore a specific thread
e-util/e-cell-text.c | 68 ++++++---
e-util/e-cell-text.h | 1 +
libemail-engine/mail-folder-cache.c | 123 ++++++++++++++-
libemail-engine/mail-ops.c | 83 ++++++++++
libemail-engine/mail-ops.h | 10 ++
mail/e-mail-reader-utils.c | 296 +++++++++++++++++++++++++++++++++++
mail/e-mail-reader-utils.h | 10 ++
mail/e-mail-reader.c | 113 +++++++++++++
mail/e-mail-reader.h | 4 +-
mail/mail.error.xml | 19 +++
mail/message-list.c | 9 +
mail/message-list.h | 3 +-
ui/evolution-mail-reader.ui | 5 +
ui/evolution-mail.ui | 4 +
14 files changed, 721 insertions(+), 27 deletions(-)
---
diff --git a/e-util/e-cell-text.c b/e-util/e-cell-text.c
index 362dbae..d12d36d 100644
--- a/e-util/e-cell-text.c
+++ b/e-util/e-cell-text.c
@@ -82,6 +82,7 @@ enum {
PROP_UNDERLINE_COLUMN,
PROP_BOLD_COLUMN,
PROP_COLOR_COLUMN,
+ PROP_ITALIC_COLUMN,
PROP_EDITABLE,
PROP_BG_COLOR_COLUMN
};
@@ -411,7 +412,7 @@ build_attr_list (ECellTextView *text_view,
ECellView *ecell_view = (ECellView *) text_view;
ECellText *ect = E_CELL_TEXT (ecell_view->ecell);
PangoAttrList *attrs = pango_attr_list_new ();
- gboolean bold, strikeout, underline;
+ gboolean bold, strikeout, underline, italic;
bold = ect->bold_column >= 0 &&
row >= 0 &&
@@ -422,29 +423,37 @@ build_attr_list (ECellTextView *text_view,
underline = ect->underline_column >= 0 &&
row >= 0 &&
e_table_model_value_at (ecell_view->e_table_model, ect->underline_column, row);
+ italic = ect->italic_column >= 0 &&
+ row >= 0 &&
+ e_table_model_value_at (ecell_view->e_table_model, ect->italic_column, row);
- if (bold || strikeout || underline) {
- if (bold) {
- PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
- attr->start_index = 0;
- attr->end_index = text_length;
+ if (bold) {
+ PangoAttribute *attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
+ attr->start_index = 0;
+ attr->end_index = text_length;
- pango_attr_list_insert_before (attrs, attr);
- }
- if (strikeout) {
- PangoAttribute *attr = pango_attr_strikethrough_new (TRUE);
- attr->start_index = 0;
- attr->end_index = text_length;
+ pango_attr_list_insert_before (attrs, attr);
+ }
+ if (strikeout) {
+ PangoAttribute *attr = pango_attr_strikethrough_new (TRUE);
+ attr->start_index = 0;
+ attr->end_index = text_length;
- pango_attr_list_insert_before (attrs, attr);
- }
- if (underline) {
- PangoAttribute *attr = pango_attr_underline_new (TRUE);
- attr->start_index = 0;
- attr->end_index = text_length;
+ pango_attr_list_insert_before (attrs, attr);
+ }
+ if (underline) {
+ PangoAttribute *attr = pango_attr_underline_new (TRUE);
+ attr->start_index = 0;
+ attr->end_index = text_length;
- pango_attr_list_insert_before (attrs, attr);
- }
+ pango_attr_list_insert_before (attrs, attr);
+ }
+ if (italic) {
+ PangoAttribute *attr = pango_attr_style_new (PANGO_STYLE_ITALIC);
+ attr->start_index = 0;
+ attr->end_index = text_length;
+
+ pango_attr_list_insert_before (attrs, attr);
}
return attrs;
}
@@ -1566,6 +1575,10 @@ ect_set_property (GObject *object,
text->bold_column = g_value_get_int (value);
break;
+ case PROP_ITALIC_COLUMN:
+ text->italic_column = g_value_get_int (value);
+ break;
+
case PROP_COLOR_COLUMN:
text->color_column = g_value_get_int (value);
break;
@@ -1607,6 +1620,10 @@ ect_get_property (GObject *object,
g_value_set_int (value, text->bold_column);
break;
+ case PROP_ITALIC_COLUMN:
+ g_value_set_int (value, text->italic_column);
+ break;
+
case PROP_COLOR_COLUMN:
g_value_set_int (value, text->color_column);
break;
@@ -1722,6 +1739,16 @@ e_cell_text_class_init (ECellTextClass *class)
g_object_class_install_property (
object_class,
+ PROP_ITALIC_COLUMN,
+ g_param_spec_int (
+ "italic-column",
+ "Italic Column",
+ NULL,
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
PROP_COLOR_COLUMN,
g_param_spec_int (
"color_column",
@@ -1916,6 +1943,7 @@ e_cell_text_init (ECellText *ect)
ect->strikeout_column = -1;
ect->underline_column = -1;
ect->bold_column = -1;
+ ect->italic_column = -1;
ect->color_column = -1;
ect->bg_color_column = -1;
ect->editable = TRUE;
diff --git a/e-util/e-cell-text.h b/e-util/e-cell-text.h
index 0d8a04c..fe7bec5 100644
--- a/e-util/e-cell-text.h
+++ b/e-util/e-cell-text.h
@@ -89,6 +89,7 @@ struct _ECellText {
gint strikeout_column;
gint underline_column;
gint bold_column;
+ gint italic_column;
/* This column in the ETable should return a string specifying a color,
* either a color name like "red" or a color spec like "rgb:F/0/0".
diff --git a/libemail-engine/mail-folder-cache.c b/libemail-engine/mail-folder-cache.c
index f5d49a3..2244c04 100644
--- a/libemail-engine/mail-folder-cache.c
+++ b/libemail-engine/mail-folder-cache.c
@@ -43,6 +43,7 @@
#include <libemail-engine/mail-mt.h>
#include "mail-folder-cache.h"
+#include "mail-ops.h"
#include "e-mail-utils.h"
#include "e-mail-folder-utils.h"
#include "e-mail-session.h"
@@ -854,12 +855,87 @@ update_1folder (MailFolderCache *cache,
}
}
+static gboolean
+folder_cache_check_ignore_thread (CamelFolder *folder,
+ CamelMessageInfo *info,
+ GCancellable *cancellable,
+ GError **error)
+{
+ const CamelSummaryReferences *references;
+ gboolean has_ignore_thread = FALSE, first_ignore_thread = FALSE, found_first_msgid = FALSE;
+ guint64 first_msgid;
+ GString *expr = NULL;
+ gint ii;
+
+ g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ references = camel_message_info_references (info);
+ if (!references || references->size <= 0)
+ return FALSE;
+
+ first_msgid = references->references[0].id.id;
+
+ for (ii = 0; ii < references->size; ii++) {
+ if (references->references[ii].id.id == 0)
+ continue;
+
+ if (!expr)
+ expr = g_string_new ("(match-all (or ");
+
+ g_string_append_printf (expr, "(= \"msgid\" \"%lu %lu\")",
+ (gulong) references->references[ii].id.part.hi,
+ (gulong) references->references[ii].id.part.lo);
+ }
+
+ if (expr) {
+ GPtrArray *uids;
+
+ g_string_append (expr, "))");
+
+ uids = camel_folder_search_by_expression (folder, expr->str, cancellable, error);
+ if (uids) {
+ for (ii = 0; ii < uids->len; ii++) {
+ const gchar *refruid = uids->pdata[ii];
+ CamelMessageInfo *refrinfo;
+
+ refrinfo = camel_folder_get_message_info (folder, refruid);
+ if (!refrinfo)
+ continue;
+
+ if (first_msgid && camel_message_info_message_id (refrinfo) &&
+ camel_message_info_message_id (refrinfo)->id.id == first_msgid) {
+ /* The first msgid in the references is In-ReplyTo, which is the
master;
+ the rest is just a guess. */
+ found_first_msgid = TRUE;
+ first_ignore_thread = camel_message_info_user_flag (refrinfo,
"ignore-thread");
+ break;
+ }
+
+ has_ignore_thread = has_ignore_thread || camel_message_info_user_flag
(refrinfo, "ignore-thread");
+
+ camel_message_info_unref (refrinfo);
+ }
+
+ camel_folder_search_free (folder, uids);
+ }
+
+ g_string_free (expr, TRUE);
+ }
+
+ return (found_first_msgid && first_ignore_thread) || (!found_first_msgid && has_ignore_thread);
+}
+
static void
-folder_changed_cb (CamelFolder *folder,
- CamelFolderChangeInfo *changes,
- MailFolderCache *cache)
+folder_cache_process_folder_changes_thread (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ GCancellable *cancellable,
+ GError **error,
+ gpointer user_data)
{
static GHashTable *last_newmail_per_folder = NULL;
+ static GMutex last_newmail_per_folder_mutex;
+ MailFolderCache *cache = user_data;
time_t latest_received, new_latest_received;
CamelFolder *local_drafts;
CamelFolder *local_outbox;
@@ -874,10 +950,15 @@ folder_changed_cb (CamelFolder *folder,
guint32 flags;
gchar *uid = NULL, *sender = NULL, *subject = NULL;
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
+ g_return_if_fail (changes != NULL);
+ g_return_if_fail (MAIL_IS_FOLDER_CACHE (cache));
+
full_name = camel_folder_get_full_name (folder);
parent_store = camel_folder_get_parent_store (folder);
session = camel_service_ref_session (CAMEL_SERVICE (parent_store));
+ g_mutex_lock (&last_newmail_per_folder_mutex);
if (last_newmail_per_folder == NULL)
last_newmail_per_folder = g_hash_table_new (
g_direct_hash, g_direct_equal);
@@ -886,6 +967,7 @@ folder_changed_cb (CamelFolder *folder,
latest_received = GPOINTER_TO_INT (
g_hash_table_lookup (last_newmail_per_folder, folder));
new_latest_received = latest_received;
+ g_mutex_unlock (&last_newmail_per_folder_mutex);
local_drafts = e_mail_session_get_local_folder (
E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS);
@@ -901,12 +983,22 @@ folder_changed_cb (CamelFolder *folder,
&& changes && (changes->uid_added->len > 0)) {
/* for each added message, check to see that it is
* brand new, not junk and not already deleted */
- for (i = 0; i < changes->uid_added->len; i++) {
+ for (i = 0; i < changes->uid_added->len && !g_cancellable_is_cancelled (cancellable); i++) {
info = camel_folder_get_message_info (
folder, changes->uid_added->pdata[i]);
if (info) {
+ GError *local_error = NULL;
+
flags = camel_message_info_flags (info);
if (((flags & CAMEL_MESSAGE_SEEN) == 0) &&
+ ((flags & CAMEL_MESSAGE_DELETED) == 0) &&
+ folder_cache_check_ignore_thread (folder, info, cancellable,
&local_error)) {
+ camel_message_info_set_flags (info, CAMEL_MESSAGE_SEEN,
CAMEL_MESSAGE_SEEN);
+ camel_message_info_set_user_flag (info, "ignore-thread", TRUE);
+ flags = flags | CAMEL_MESSAGE_SEEN;
+ }
+
+ if (((flags & CAMEL_MESSAGE_SEEN) == 0) &&
((flags & CAMEL_MESSAGE_JUNK) == 0) &&
((flags & CAMEL_MESSAGE_DELETED) == 0) &&
(camel_message_info_date_received (info) > latest_received)) {
@@ -929,14 +1021,22 @@ folder_changed_cb (CamelFolder *folder,
}
camel_message_info_unref (info);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ break;
+ }
}
}
}
- if (new > 0)
+ if (new > 0) {
+ g_mutex_lock (&last_newmail_per_folder_mutex);
g_hash_table_insert (
last_newmail_per_folder, folder,
GINT_TO_POINTER (new_latest_received));
+ g_mutex_unlock (&last_newmail_per_folder_mutex);
+ }
folder_info = mail_folder_cache_ref_folder_info (
cache, parent_store, full_name);
@@ -955,6 +1055,19 @@ folder_changed_cb (CamelFolder *folder,
}
static void
+folder_changed_cb (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ MailFolderCache *cache)
+{
+ if (!changes)
+ return;
+
+ mail_process_folder_changes (folder, changes,
+ folder_cache_process_folder_changes_thread,
+ g_object_unref, g_object_ref (cache));
+}
+
+static void
unset_folder_info (MailFolderCache *cache,
FolderInfo *folder_info,
gint delete)
diff --git a/libemail-engine/mail-ops.c b/libemail-engine/mail-ops.c
index a2b3bf1..af4cd9a 100644
--- a/libemail-engine/mail-ops.c
+++ b/libemail-engine/mail-ops.c
@@ -1532,3 +1532,86 @@ mail_execute_shell_command (CamelFilterDriver *driver,
g_spawn_async (NULL, argv, NULL, 0, NULL, data, NULL, NULL);
}
+/* ** Process Folder Changes *********************************************** */
+
+struct _process_folder_changes_msg {
+ MailMsg base;
+
+ CamelFolder *folder;
+ CamelFolderChangeInfo *changes;
+ void (*process) (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ GCancellable *cancellable,
+ GError **error,
+ gpointer user_data);
+ void (* done) (gpointer user_data);
+ gpointer user_data;
+};
+
+static gchar *
+process_folder_changes_desc (struct _process_folder_changes_msg *m)
+{
+ return g_strdup_printf (
+ _("Processing folder changes in '%s'"), camel_folder_get_full_name (m->folder));
+}
+
+static void
+process_folder_changes_exec (struct _process_folder_changes_msg *m,
+ GCancellable *cancellable,
+ GError **error)
+{
+ m->process (m->folder, m->changes, cancellable, error, m->user_data);
+}
+
+static void
+process_folder_changes_done (struct _process_folder_changes_msg *m)
+{
+ if (m->done)
+ m->done (m->user_data);
+}
+
+static void
+process_folder_changes_free (struct _process_folder_changes_msg *m)
+{
+ g_clear_object (&m->folder);
+ camel_folder_change_info_free (m->changes);
+}
+
+static MailMsgInfo process_folder_changes_info = {
+ sizeof (struct _process_folder_changes_msg),
+ (MailMsgDescFunc) process_folder_changes_desc,
+ (MailMsgExecFunc) process_folder_changes_exec,
+ (MailMsgDoneFunc) process_folder_changes_done,
+ (MailMsgFreeFunc) process_folder_changes_free
+};
+
+void
+mail_process_folder_changes (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ void (*process) (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ GCancellable *cancellable,
+ GError **error,
+ gpointer user_data),
+ void (* done) (gpointer user_data),
+ gpointer user_data)
+{
+ struct _process_folder_changes_msg *m;
+ CamelFolderChangeInfo *changes_copy;
+
+ g_return_if_fail (CAMEL_IS_FOLDER (folder));
+ g_return_if_fail (changes != NULL);
+ g_return_if_fail (process != NULL);
+
+ changes_copy = camel_folder_change_info_new ();
+ camel_folder_change_info_cat (changes_copy, changes);
+
+ m = mail_msg_new (&process_folder_changes_info);
+ m->folder = g_object_ref (folder);
+ m->changes = changes_copy;
+ m->process = process;
+ m->done = done;
+ m->user_data = user_data;
+
+ mail_msg_unordered_push (m);
+}
diff --git a/libemail-engine/mail-ops.h b/libemail-engine/mail-ops.h
index 12680cf..cfc0831 100644
--- a/libemail-engine/mail-ops.h
+++ b/libemail-engine/mail-ops.h
@@ -90,6 +90,16 @@ void mail_filter_folder (EMailSession *session,
const gchar *type,
gboolean notify);
+void mail_process_folder_changes (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ void (*process) (CamelFolder *folder,
+ CamelFolderChangeInfo *changes,
+ GCancellable *cancellable,
+ GError **error,
+ gpointer user_data),
+ void (* done) (gpointer user_data),
+ gpointer user_data);
+
/* filter driver execute shell command async callback */
void mail_execute_shell_command (CamelFilterDriver *driver, gint argc, gchar **argv, gpointer data);
diff --git a/mail/e-mail-reader-utils.c b/mail/e-mail-reader-utils.c
index 4a959ba..9fccee8 100644
--- a/mail/e-mail-reader-utils.c
+++ b/mail/e-mail-reader-utils.c
@@ -773,6 +773,302 @@ e_mail_reader_mark_selected (EMailReader *reader,
return ii;
}
+static guint
+summary_msgid_hash (gconstpointer key)
+{
+ const CamelSummaryMessageID *id = (const CamelSummaryMessageID *) key;
+
+ return id->id.part.lo;
+}
+
+static gboolean
+summary_msgid_equal (gconstpointer a,
+ gconstpointer b)
+{
+ return ((const CamelSummaryMessageID *) a)->id.id == ((const CamelSummaryMessageID *) b)->id.id;
+}
+
+typedef struct {
+ CamelFolder *folder;
+ GSList *uids;
+ EIgnoreThreadKind kind;
+} MarkIgnoreThreadData;
+
+static void
+mark_ignore_thread_data_free (gpointer ptr)
+{
+ MarkIgnoreThreadData *mit = ptr;
+
+ if (mit) {
+ g_clear_object (&mit->folder);
+ g_slist_free_full (mit->uids, (GDestroyNotify) camel_pstring_free);
+ g_free (mit);
+ }
+}
+
+static void
+insert_to_checked_msgids (GHashTable *checked_msgids,
+ const CamelSummaryMessageID *msgid)
+{
+ CamelSummaryMessageID *msgid_copy;
+
+ if (!msgid)
+ return;
+
+ msgid_copy = g_new0 (CamelSummaryMessageID, 1);
+ memcpy (msgid_copy, msgid, sizeof (CamelSummaryMessageID));
+
+ g_hash_table_insert (checked_msgids, msgid_copy, GINT_TO_POINTER (1));
+}
+
+static gboolean
+mark_ignore_thread_traverse_uids (CamelFolder *folder,
+ const gchar *uid,
+ GHashTable *checked_uids,
+ GHashTable *checked_msgids,
+ gboolean whole_thread,
+ gboolean ignore_thread,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GSList *to_check;
+ GPtrArray *uids;
+ gint ii;
+ gboolean success;
+
+ success = !g_cancellable_set_error_if_cancelled (cancellable, error);
+ if (!success)
+ return success;
+
+ if (g_hash_table_contains (checked_uids, uid))
+ return success;
+
+ to_check = g_slist_prepend (NULL, (gpointer) camel_pstring_strdup (uid));
+
+ while (to_check != NULL && !g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ CamelMessageInfo *mi;
+ const CamelSummaryMessageID *msgid;
+ const CamelSummaryReferences *references;
+ const gchar *uid = to_check->data;
+ gchar *sexp;
+ GError *local_error = NULL;
+
+ to_check = g_slist_remove (to_check, uid);
+
+ if (!uid || g_hash_table_contains (checked_uids, uid)) {
+ camel_pstring_free (uid);
+ continue;
+ }
+
+ g_hash_table_insert (checked_uids, (gpointer) camel_pstring_strdup (uid), GINT_TO_POINTER
(1));
+
+ mi = camel_folder_get_message_info (folder, uid);
+ if (!mi || !camel_message_info_message_id (mi)) {
+ camel_pstring_free (uid);
+ continue;
+ }
+
+ camel_message_info_set_user_flag (mi, "ignore-thread", ignore_thread);
+
+ msgid = camel_message_info_message_id (mi);
+ insert_to_checked_msgids (checked_msgids, msgid);
+
+ if (whole_thread) {
+ /* Search for parents */
+ references = camel_message_info_references (mi);
+ if (references) {
+ GString *expr = NULL;
+
+ for (ii = 0; ii < references->size; ii++) {
+ if (references->references[ii].id.id == 0 ||
+ g_hash_table_contains (checked_msgids,
&references->references[ii]))
+ continue;
+
+ insert_to_checked_msgids (checked_msgids,
&references->references[ii]);
+
+ if (!expr)
+ expr = g_string_new ("(match-all (or ");
+
+ g_string_append_printf (expr, "(= \"msgid\" \"%lu %lu\")",
+ (gulong) references->references[ii].id.part.hi,
+ (gulong) references->references[ii].id.part.lo);
+ }
+
+ if (expr) {
+ g_string_append (expr, "))");
+
+ uids = camel_folder_search_by_expression (folder, expr->str,
cancellable, &local_error);
+ if (uids) {
+ for (ii = 0; ii < uids->len; ii++) {
+ const gchar *refruid = uids->pdata[ii];
+
+ if (refruid && !g_hash_table_contains (checked_uids,
refruid))
+ to_check = g_slist_prepend (to_check,
(gpointer) camel_pstring_strdup (refruid));
+ }
+
+ camel_folder_search_free (folder, uids);
+ }
+
+ g_string_free (expr, TRUE);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ camel_message_info_unref (mi);
+ camel_pstring_free (uid);
+ success = FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Search for children */
+ sexp = g_strdup_printf ("(match-all (= \"references\" \"%lu %lu\"))", (gulong)
msgid->id.part.hi, (gulong) msgid->id.part.lo);
+ uids = camel_folder_search_by_expression (folder, sexp, cancellable, &local_error);
+ if (uids) {
+ for (ii = 0; ii < uids->len; ii++) {
+ const gchar *refruid = uids->pdata[ii];
+
+ if (refruid && !g_hash_table_contains (checked_uids, refruid)) {
+ CamelMessageInfo *refrmi = camel_folder_get_message_info (folder,
refruid);
+
+ if (refrmi && camel_message_info_message_id (refrmi) &&
+ !g_hash_table_contains (checked_msgids,
camel_message_info_message_id (refrmi))) {
+ /* The 'references' filter search can return false positives
*/
+ references = camel_message_info_references (refrmi);
+ if (references) {
+ gint jj;
+
+ for (jj = 0; jj < references->size; jj++) {
+ if (references->references[jj].id.id ==
msgid->id.id) {
+ to_check = g_slist_prepend (to_check,
(gpointer) camel_pstring_strdup (refruid));
+ break;
+ }
+ }
+ }
+ }
+
+ if (refrmi)
+ camel_message_info_unref (refrmi);
+ }
+ }
+
+ camel_folder_search_free (folder, uids);
+ }
+ g_free (sexp);
+
+ camel_message_info_unref (mi);
+ camel_pstring_free (uid);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ success = FALSE;
+ break;
+ }
+ }
+
+ g_slist_free_full (to_check, (GDestroyNotify) camel_pstring_free);
+
+ return success;
+}
+
+static void
+mail_reader_utils_mark_ignore_thread_thread (EAlertSinkThreadJobData *job_data,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ MarkIgnoreThreadData *mit = user_data;
+ GHashTable *checked_uids; /* gchar * (UID) ~> 1 */
+ GHashTable *checked_msgids; /* CamelSummaryMessageID * ~> 1 */
+ gboolean ignore_thread, whole_thread;
+ GSList *link;
+
+ g_return_if_fail (mit != NULL);
+
+ camel_folder_freeze (mit->folder);
+
+ whole_thread = mit->kind == E_IGNORE_THREAD_WHOLE_SET || mit->kind == E_IGNORE_THREAD_WHOLE_UNSET;
+ ignore_thread = mit->kind == E_IGNORE_THREAD_WHOLE_SET || mit->kind == E_IGNORE_THREAD_SUBSET_SET;
+
+ checked_uids = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free,
NULL);
+ checked_msgids = g_hash_table_new_full (summary_msgid_hash, summary_msgid_equal, g_free, NULL);
+
+ for (link = mit->uids; link; link = g_slist_next (link)) {
+ if (!mark_ignore_thread_traverse_uids (mit->folder, link->data, checked_uids, checked_msgids,
+ whole_thread, ignore_thread, cancellable, error)) {
+ break;
+ }
+ }
+
+ camel_folder_thaw (mit->folder);
+
+ g_hash_table_destroy (checked_msgids);
+ g_hash_table_destroy (checked_uids);
+}
+
+void
+e_mail_reader_mark_selected_ignore_thread (EMailReader *reader,
+ EIgnoreThreadKind kind)
+{
+ CamelFolder *folder;
+
+ g_return_if_fail (E_IS_MAIL_READER (reader));
+
+ folder = e_mail_reader_ref_folder (reader);
+
+ if (folder != NULL) {
+ GPtrArray *uids;
+ guint ii;
+
+ uids = e_mail_reader_get_selected_uids (reader);
+ if (uids && uids->len > 0) {
+ MarkIgnoreThreadData *mit;
+ EAlertSink *alert_sink;
+ EActivity *activity;
+ const gchar *description = NULL, *alert_id = NULL;
+
+ switch (kind) {
+ case E_IGNORE_THREAD_WHOLE_SET:
+ description = _("Marking thread to be ignored");
+ alert_id = "mail:failed-mark-ignore-thread";
+ break;
+ case E_IGNORE_THREAD_WHOLE_UNSET:
+ description = _("Unmarking thread from being ignored");
+ alert_id = "mail:failed-mark-unignore-thread";
+ break;
+ case E_IGNORE_THREAD_SUBSET_SET:
+ description = _("Marking sub-thread to be ignored");
+ alert_id = "mail:failed-mark-ignore-subthread";
+ break;
+ case E_IGNORE_THREAD_SUBSET_UNSET:
+ description = _("Unmarking sub-thread from being ignored");
+ alert_id = "mail:failed-mark-unignore-subthread";
+ break;
+ }
+
+ mit = g_new0 (MarkIgnoreThreadData, 1);
+ mit->folder = g_object_ref (folder);
+ mit->kind = kind;
+
+ for (ii = 0; ii < uids->len; ii++) {
+ mit->uids = g_slist_prepend (mit->uids, (gpointer) camel_pstring_strdup
(uids->pdata[ii]));
+ }
+
+ alert_sink = e_mail_reader_get_alert_sink (reader);
+
+ activity = e_alert_sink_submit_thread_job (alert_sink, description, alert_id,
+ camel_folder_get_full_name (folder),
mail_reader_utils_mark_ignore_thread_thread,
+ mit, mark_ignore_thread_data_free);
+
+ g_clear_object (&activity);
+ }
+
+ g_ptr_array_unref (uids);
+ g_object_unref (folder);
+ }
+}
+
static void
copy_tree_state (EMailReader *src_reader,
EMailReader *des_reader)
diff --git a/mail/e-mail-reader-utils.h b/mail/e-mail-reader-utils.h
index 32c6ae0..a1366f8 100644
--- a/mail/e-mail-reader-utils.h
+++ b/mail/e-mail-reader-utils.h
@@ -53,6 +53,16 @@ void e_mail_reader_unsubscribe_folder_name
guint e_mail_reader_mark_selected (EMailReader *reader,
guint32 mask,
guint32 set);
+typedef enum {
+ E_IGNORE_THREAD_WHOLE_SET,
+ E_IGNORE_THREAD_WHOLE_UNSET,
+ E_IGNORE_THREAD_SUBSET_SET,
+ E_IGNORE_THREAD_SUBSET_UNSET
+} EIgnoreThreadKind;
+
+void e_mail_reader_mark_selected_ignore_thread
+ (EMailReader *reader,
+ EIgnoreThreadKind kind);
guint e_mail_reader_open_selected (EMailReader *reader);
void e_mail_reader_print (EMailReader *reader,
GtkPrintOperationAction action);
diff --git a/mail/e-mail-reader.c b/mail/e-mail-reader.c
index c269a50..202ec2d 100644
--- a/mail/e-mail-reader.c
+++ b/mail/e-mail-reader.c
@@ -734,6 +734,34 @@ action_mail_mark_unimportant_cb (GtkAction *action,
}
static void
+action_mail_mark_ignore_thread_sub_cb (GtkAction *action,
+ EMailReader *reader)
+{
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_SET);
+}
+
+static void
+action_mail_mark_unignore_thread_sub_cb (GtkAction *action,
+ EMailReader *reader)
+{
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_UNSET);
+}
+
+static void
+action_mail_mark_ignore_thread_whole_cb (GtkAction *action,
+ EMailReader *reader)
+{
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_SET);
+}
+
+static void
+action_mail_mark_unignore_thread_whole_cb (GtkAction *action,
+ EMailReader *reader)
+{
+ e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_UNSET);
+}
+
+static void
action_mail_mark_unread_cb (GtkAction *action,
EMailReader *reader)
{
@@ -2110,6 +2138,20 @@ static GtkActionEntry mail_reader_entries[] = {
N_("Force images in HTML mail to be loaded"),
G_CALLBACK (action_mail_load_images_cb) },
+ { "mail-mark-ignore-thread-sub",
+ NULL,
+ N_("_Ignore Sub-Thread"),
+ NULL,
+ N_("Mark new mails in a sub-thread as read automatically"),
+ G_CALLBACK (action_mail_mark_ignore_thread_sub_cb) },
+
+ { "mail-mark-ignore-thread-whole",
+ NULL,
+ N_("_Ignore Thread"),
+ NULL,
+ N_("Mark new mails in this thread as read automatically"),
+ G_CALLBACK (action_mail_mark_ignore_thread_whole_cb) },
+
{ "mail-mark-important",
"mail-mark-important",
N_("_Important"),
@@ -2138,6 +2180,20 @@ static GtkActionEntry mail_reader_entries[] = {
N_("Mark the selected messages as having been read"),
G_CALLBACK (action_mail_mark_read_cb) },
+ { "mail-mark-unignore-thread-sub",
+ NULL,
+ N_("Do not _Ignore Sub-Thread"),
+ NULL,
+ N_("Do not mark new mails in a sub-thread as read automatically"),
+ G_CALLBACK (action_mail_mark_unignore_thread_sub_cb) },
+
+ { "mail-mark-unignore-thread-whole",
+ NULL,
+ N_("Do not _Ignore Thread"),
+ NULL,
+ N_("Do not mark new mails in this thread as read automatically"),
+ G_CALLBACK (action_mail_mark_unignore_thread_whole_cb) },
+
{ "mail-mark-unimportant",
NULL,
N_("Uni_mportant"),
@@ -2461,6 +2517,14 @@ static EPopupActionEntry mail_reader_popup_entries[] = {
NULL,
"mail-forward" },
+ { "mail-popup-mark-ignore-thread-sub",
+ N_("_Ignore Sub-Thread"),
+ "mail-mark-ignore-thread-sub" },
+
+ { "mail-popup-mark-ignore-thread-whole",
+ N_("_Ignore Thread"),
+ "mail-mark-ignore-thread-whole" },
+
{ "mail-popup-mark-important",
N_("Mark as _Important"),
"mail-mark-important" },
@@ -2477,6 +2541,14 @@ static EPopupActionEntry mail_reader_popup_entries[] = {
N_("Mar_k as Read"),
"mail-mark-read" },
+ { "mail-popup-mark-unignore-thread-sub",
+ N_("Do not _Ignore Sub-Thread"),
+ "mail-mark-unignore-thread-sub" },
+
+ { "mail-popup-mark-unignore-thread-whole",
+ N_("Do not _Ignore Thread"),
+ "mail-mark-unignore-thread-whole" },
+
{ "mail-popup-mark-unimportant",
N_("Mark as Uni_mportant"),
"mail-mark-unimportant" },
@@ -3396,6 +3468,8 @@ mail_reader_update_actions (EMailReader *reader,
gboolean multiple_messages_selected;
gboolean selection_has_attachment_messages;
gboolean selection_has_deleted_messages;
+ gboolean selection_has_ignore_thread_messages;
+ gboolean selection_has_notignore_thread_messages;
gboolean selection_has_important_messages;
gboolean selection_has_junk_messages;
gboolean selection_has_not_junk_messages;
@@ -3425,6 +3499,10 @@ mail_reader_update_actions (EMailReader *reader,
(state & E_MAIL_READER_SELECTION_HAS_ATTACHMENTS);
selection_has_deleted_messages =
(state & E_MAIL_READER_SELECTION_HAS_DELETED);
+ selection_has_ignore_thread_messages =
+ (state & E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD);
+ selection_has_notignore_thread_messages =
+ (state & E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD);
selection_has_important_messages =
(state & E_MAIL_READER_SELECTION_HAS_IMPORTANT);
selection_has_junk_messages =
@@ -3584,6 +3662,18 @@ mail_reader_update_actions (EMailReader *reader,
action = e_mail_reader_get_action (reader, action_name);
gtk_action_set_sensitive (action, sensitive);
+ action_name = "mail-mark-ignore-thread-sub";
+ sensitive = selection_has_notignore_thread_messages;
+ action = e_mail_reader_get_action (reader, action_name);
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_visible (action, sensitive);
+
+ action_name = "mail-mark-ignore-thread-whole";
+ sensitive = selection_has_notignore_thread_messages;
+ action = e_mail_reader_get_action (reader, action_name);
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_visible (action, sensitive);
+
action_name = "mail-mark-important";
sensitive = selection_has_unimportant_messages;
action = e_mail_reader_get_action (reader, action_name);
@@ -3606,6 +3696,18 @@ mail_reader_update_actions (EMailReader *reader,
action = e_mail_reader_get_action (reader, action_name);
gtk_action_set_sensitive (action, sensitive);
+ action_name = "mail-mark-unignore-thread-sub";
+ sensitive = selection_has_ignore_thread_messages;
+ action = e_mail_reader_get_action (reader, action_name);
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_visible (action, sensitive);
+
+ action_name = "mail-mark-unignore-thread-whole";
+ sensitive = selection_has_ignore_thread_messages;
+ action = e_mail_reader_get_action (reader, action_name);
+ gtk_action_set_sensitive (action, sensitive);
+ gtk_action_set_visible (action, sensitive);
+
action_name = "mail-mark-unimportant";
sensitive = selection_has_important_messages;
action = e_mail_reader_get_action (reader, action_name);
@@ -4203,6 +4305,8 @@ e_mail_reader_check_state (EMailReader *reader)
gboolean can_flag_for_followup = FALSE;
gboolean has_attachments = FALSE;
gboolean has_deleted = FALSE;
+ gboolean has_ignore_thread = FALSE;
+ gboolean has_notignore_thread = FALSE;
gboolean has_important = FALSE;
gboolean has_junk = FALSE;
gboolean has_not_junk = FALSE;
@@ -4330,6 +4434,11 @@ e_mail_reader_check_state (EMailReader *reader)
string = camel_message_info_mlist (info);
is_mailing_list &= (string != NULL && *string != '\0');
+ has_ignore_thread = has_ignore_thread ||
+ camel_message_info_user_flag (info, "ignore-thread");
+ has_notignore_thread = has_notignore_thread ||
+ !camel_message_info_user_flag (info, "ignore-thread");
+
camel_message_info_unref (info);
}
@@ -4355,6 +4464,10 @@ e_mail_reader_check_state (EMailReader *reader)
state |= E_MAIL_READER_SELECTION_HAS_ATTACHMENTS;
if (has_deleted)
state |= E_MAIL_READER_SELECTION_HAS_DELETED;
+ if (has_ignore_thread)
+ state |= E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD;
+ if (has_notignore_thread)
+ state |= E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD;
if (has_important)
state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT;
if (has_junk)
diff --git a/mail/e-mail-reader.h b/mail/e-mail-reader.h
index 0d83e81..baae723 100644
--- a/mail/e-mail-reader.h
+++ b/mail/e-mail-reader.h
@@ -88,7 +88,9 @@ enum {
E_MAIL_READER_SELECTION_IS_MAILING_LIST = 1 << 16,
E_MAIL_READER_FOLDER_IS_JUNK = 1 << 17,
E_MAIL_READER_FOLDER_IS_VTRASH = 1 << 18,
- E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET = 1 << 19
+ E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET = 1 << 19,
+ E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD = 1 << 20,
+ E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD = 1 << 21
};
struct _EMailReaderInterface {
diff --git a/mail/mail.error.xml b/mail/mail.error.xml
index c3e12fd..c248a1a 100644
--- a/mail/mail.error.xml
+++ b/mail/mail.error.xml
@@ -541,5 +541,24 @@ An mbox account will be created to preserve the old mbox folders. You can delete
<secondary>{1}</secondary>
</error>
+ <error id="failed-mark-ignore-thread" type="error" default="GTK_RESPONSE_YES">
+ <_primary>Failed to mark thread to be ignored in folder '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="failed-mark-unignore-thread" type="error" default="GTK_RESPONSE_YES">
+ <_primary>Failed to unmark thread from being ignored in folder '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="failed-mark-ignore-subthread" type="error" default="GTK_RESPONSE_YES">
+ <_primary>Failed to mark sub-thread to be ignored in folder '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
+
+ <error id="failed-mark-unignore-subthread" type="error" default="GTK_RESPONSE_YES">
+ <_primary>Failed to unmark sub-thread from being ignored in folder '{0}'</_primary>
+ <secondary>{1}</secondary>
+ </error>
</error-list>
diff --git a/mail/message-list.c b/mail/message-list.c
index 43a0750..a47e6ff 100644
--- a/mail/message-list.c
+++ b/mail/message-list.c
@@ -1792,6 +1792,9 @@ ml_tree_value_at_ex (ETreeModel *etm,
return (gpointer) colour;
}
+ case COL_ITALIC: {
+ return GINT_TO_POINTER (camel_message_info_user_flag (msg_info, "ignore-thread") ? 1 : 0);
+ }
case COL_LOCATION: {
/* Fixme : freeing memory stuff (mem leaks) */
CamelStore *store;
@@ -1961,6 +1964,7 @@ static ECell * create_composite_cell (gint col)
g_object_set (
cell_date,
"bold_column", COL_UNREAD,
+ "italic-column", COL_ITALIC,
"color_column", COL_COLOUR,
NULL);
@@ -1968,6 +1972,7 @@ static ECell * create_composite_cell (gint col)
g_object_set (
cell_from,
"bold_column", COL_UNREAD,
+ "italic-column", COL_ITALIC,
"color_column", COL_COLOUR,
NULL);
@@ -2053,6 +2058,7 @@ message_list_create_extras (void)
g_object_set (
cell,
"bold_column", COL_UNREAD,
+ "italic-column", COL_ITALIC,
"color_column", COL_COLOUR,
NULL);
e_table_extras_add_cell (extras, "render_date", cell);
@@ -2063,6 +2069,7 @@ message_list_create_extras (void)
g_object_set (
cell,
"bold_column", COL_UNREAD,
+ "italic-column", COL_ITALIC,
"color_column", COL_COLOUR,
NULL);
e_table_extras_add_cell (extras, "render_text", cell);
@@ -2077,6 +2084,7 @@ message_list_create_extras (void)
g_object_set (
cell,
"bold_column", COL_UNREAD,
+ "italic-column", COL_ITALIC,
"color_column", COL_COLOUR,
NULL);
e_table_extras_add_cell (extras, "render_size", cell);
@@ -3057,6 +3065,7 @@ message_list_free_value (ETreeModel *tree_model,
case COL_SUBJECT_NORM:
case COL_SUBJECT_TRIMMED:
case COL_COLOUR:
+ case COL_ITALIC:
break;
case COL_LOCATION:
diff --git a/mail/message-list.h b/mail/message-list.h
index 6309c7e..ebc8a4e 100644
--- a/mail/message-list.h
+++ b/mail/message-list.h
@@ -83,7 +83,8 @@ enum {
/* Invisible columns */
COL_DELETED,
COL_UNREAD,
- COL_COLOUR
+ COL_COLOUR,
+ COL_ITALIC
};
#define MESSAGE_LIST_COLUMN_IS_ACTIVE(col) (col == COL_MESSAGE_STATUS || \
diff --git a/ui/evolution-mail-reader.ui b/ui/evolution-mail-reader.ui
index 0e772b6..041c295 100644
--- a/ui/evolution-mail-reader.ui
+++ b/ui/evolution-mail-reader.ui
@@ -87,6 +87,11 @@
<menuitem action="mail-flag-for-followup"/>
<menuitem action="mail-flag-clear"/>
<menuitem action="mail-flag-completed"/>
+ <separator/>
+ <menuitem action="mail-mark-ignore-thread-whole"/>
+ <menuitem action="mail-mark-ignore-thread-sub"/>
+ <menuitem action="mail-mark-unignore-thread-whole"/>
+ <menuitem action="mail-mark-unignore-thread-sub"/>
</menu>
<menuitem action='mail-filters-apply'/>
<menuitem action='mail-check-for-junk'/>
diff --git a/ui/evolution-mail.ui b/ui/evolution-mail.ui
index c8fc9f2..e3d5dca 100644
--- a/ui/evolution-mail.ui
+++ b/ui/evolution-mail.ui
@@ -112,6 +112,10 @@
<menuitem action='mail-popup-flag-for-followup'/>
<menuitem action="mail-popup-flag-clear"/>
<menuitem action="mail-popup-flag-completed"/>
+ <menuitem action='mail-popup-mark-ignore-thread-whole'/>
+ <menuitem action='mail-popup-mark-ignore-thread-sub'/>
+ <menuitem action='mail-popup-mark-unignore-thread-whole'/>
+ <menuitem action='mail-popup-mark-unignore-thread-sub'/>
<menu action='mail-label-menu'>
<menuitem action='mail-label-none'/>
<separator/>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]