aboutsummaryrefslogtreecommitdiffstats
path: root/libemail-engine/mail-vfolder.c
diff options
context:
space:
mode:
Diffstat (limited to 'libemail-engine/mail-vfolder.c')
-rw-r--r--libemail-engine/mail-vfolder.c245
1 files changed, 167 insertions, 78 deletions
diff --git a/libemail-engine/mail-vfolder.c b/libemail-engine/mail-vfolder.c
index 08e6e22fe5..233e6a0f02 100644
--- a/libemail-engine/mail-vfolder.c
+++ b/libemail-engine/mail-vfolder.c
@@ -60,6 +60,59 @@ static void rule_changed (EFilterRule *rule, CamelFolder *folder);
/* ********************************************************************** */
+static GList *
+vfolder_get_include_subfolders_uris (EMailSession *session,
+ const gchar *base_uri,
+ GCancellable *cancellable)
+{
+ GList *uris = NULL;
+ CamelStore *store = NULL;
+ gchar *folder_name = NULL;
+ CamelFolderInfo *fi;
+ const CamelFolderInfo *cur;
+
+ g_return_val_if_fail (session != NULL, NULL);
+ g_return_val_if_fail (base_uri != NULL, NULL);
+ g_return_val_if_fail (*base_uri == '*', NULL);
+
+ if (!e_mail_folder_uri_parse (CAMEL_SESSION (session), base_uri + 1, &store, &folder_name, NULL))
+ return NULL;
+
+ fi = camel_store_get_folder_info_sync (store, folder_name,
+ CAMEL_STORE_FOLDER_INFO_RECURSIVE, cancellable, NULL);
+ cur = fi;
+ while (cur) {
+ if ((cur->flags & CAMEL_FOLDER_NOSELECT) == 0) {
+ gchar *fi_uri = e_mail_folder_uri_build (store, cur->full_name);
+
+ if (fi_uri)
+ uris = g_list_prepend (uris, fi_uri);
+ }
+
+ /* move to the next fi */
+ if (cur->child) {
+ cur = cur->child;
+ } else if (cur->next) {
+ cur = cur->next;
+ } else {
+ while (cur && !cur->next) {
+ cur = cur->parent;
+ }
+
+ if (cur)
+ cur = cur->next;
+ }
+ }
+
+ if (fi)
+ camel_store_free_folder_info (store, fi);
+
+ g_object_unref (store);
+ g_free (folder_name);
+
+ return g_list_reverse (uris);
+}
+
struct _setup_msg {
MailMsg base;
@@ -67,7 +120,6 @@ struct _setup_msg {
CamelFolder *folder;
gchar *query;
GList *sources_uri;
- GList *sources_folder;
};
static gchar *
@@ -88,34 +140,42 @@ vfolder_setup_exec (struct _setup_msg *m,
camel_vee_folder_set_expression ((CamelVeeFolder *) m->folder, m->query);
- l = m->sources_uri;
- while (l && !vfolder_shutdown) {
- d(printf(" Adding uri: %s\n", (gchar *)l->data));
+ for (l = m->sources_uri;
+ l && !vfolder_shutdown && !g_cancellable_is_cancelled (cancellable);
+ l = l->next) {
+ const gchar *uri = l->data;
- /* FIXME Not passing a GCancellable or GError here. */
- folder = e_mail_session_uri_to_folder_sync (
- m->session, l->data, 0, NULL, NULL);
- if (folder != NULL)
- list = g_list_append (list, folder);
- l = l->next;
- }
+ d(printf(" Adding uri: %s\n", uri));
- l = m->sources_folder;
- while (l && !vfolder_shutdown) {
- g_object_ref (l->data);
- list = g_list_append (list, l->data);
- l = l->next;
+ if (!uri || !*uri || !uri[1])
+ continue;
+
+ if (*uri == '*') {
+ /* include folder and its subfolders */
+ GList *uris, *iter;
+
+ uris = vfolder_get_include_subfolders_uris (m->session, uri, cancellable);
+ for (iter = uris; iter; iter = iter->next) {
+ const gchar *fi_uri = iter->data;
+
+ folder = e_mail_session_uri_to_folder_sync (
+ m->session, fi_uri, 0, cancellable, NULL);
+ if (folder != NULL)
+ list = g_list_append (list, folder);
+ }
+
+ g_list_free_full (uris, g_free);
+ } else {
+ folder = e_mail_session_uri_to_folder_sync (m->session, l->data, 0, cancellable, NULL);
+ if (folder != NULL)
+ list = g_list_append (list, folder);
+ }
}
- if (!vfolder_shutdown)
+ if (!vfolder_shutdown && !g_cancellable_is_cancelled (cancellable))
camel_vee_folder_set_folders ((CamelVeeFolder *) m->folder, list, cancellable);
- l = list;
- while (l) {
- g_object_unref (l->data);
- l = l->next;
- }
- g_list_free (list);
+ g_list_free_full (list, g_object_unref);
}
static void
@@ -126,27 +186,12 @@ vfolder_setup_done (struct _setup_msg *m)
static void
vfolder_setup_free (struct _setup_msg *m)
{
- GList *l;
-
camel_folder_thaw (m->folder);
g_object_unref (m->session);
g_object_unref (m->folder);
g_free (m->query);
-
- l = m->sources_uri;
- while (l) {
- g_free (l->data);
- l = l->next;
- }
- g_list_free (m->sources_uri);
-
- l = m->sources_folder;
- while (l) {
- g_object_unref (l->data);
- l = l->next;
- }
- g_list_free (m->sources_folder);
+ g_list_free_full (m->sources_uri, g_free);
}
static MailMsgInfo vfolder_setup_info = {
@@ -162,8 +207,7 @@ static gint
vfolder_setup (EMailSession *session,
CamelFolder *folder,
const gchar *query,
- GList *sources_uri,
- GList *sources_folder)
+ GList *sources_uri)
{
struct _setup_msg *m;
gint id;
@@ -173,7 +217,6 @@ vfolder_setup (EMailSession *session,
m->folder = g_object_ref (folder);
m->query = g_strdup (query);
m->sources_uri = sources_uri;
- m->sources_folder = sources_folder;
camel_folder_freeze (m->folder);
@@ -185,6 +228,27 @@ vfolder_setup (EMailSession *session,
/* ********************************************************************** */
+static void
+vfolder_add_remove_one (GList *vfolders,
+ gboolean remove,
+ CamelFolder *folder,
+ GCancellable *cancellable)
+{
+ GList *iter;
+
+ for (iter = vfolders; iter && !vfolder_shutdown; iter = iter->next) {
+ CamelVeeFolder *vfolder = CAMEL_VEE_FOLDER (iter->data);
+
+ if (!vfolder)
+ continue;
+
+ if (remove)
+ camel_vee_folder_remove_folder (vfolder, folder, cancellable);
+ else
+ camel_vee_folder_add_folder (vfolder, folder, cancellable);
+ }
+}
+
struct _adduri_msg {
MailMsg base;
@@ -229,7 +293,6 @@ vfolder_adduri_exec (struct _adduri_msg *m,
GCancellable *cancellable,
GError **error)
{
- GList *l;
CamelFolder *folder = NULL;
MailFolderCache *folder_cache;
@@ -241,29 +304,39 @@ vfolder_adduri_exec (struct _adduri_msg *m,
/* we dont try lookup the cache if we are removing it, its no longer there */
if (!m->remove &&
- !mail_folder_cache_get_folder_from_uri (folder_cache, m->uri, NULL)) {
+ !mail_folder_cache_get_folder_from_uri (folder_cache, m->uri[0] == '*' ? m->uri + 1 : m->uri, NULL)) {
g_warning (
"Folder '%s' disappeared while I was "
"adding/removing it to/from my vfolder", m->uri);
return;
}
- /* always pick fresh folders - they are
- * from CamelStore's folders bag anyway */
- folder = e_mail_session_uri_to_folder_sync (
- m->session, m->uri, 0, cancellable, error);
-
- if (folder != NULL) {
- l = m->folders;
- while (l && !vfolder_shutdown) {
- if (m->remove)
- camel_vee_folder_remove_folder (
- CAMEL_VEE_FOLDER (l->data), folder, cancellable);
- else
- camel_vee_folder_add_folder ((CamelVeeFolder *) l->data, folder, cancellable);
- l = l->next;
+ if (m->uri[0] == '*') {
+ GList *uris, *iter;
+
+ uris = vfolder_get_include_subfolders_uris (m->session, m->uri, cancellable);
+ for (iter = uris; iter; iter = iter->next) {
+ const gchar *fi_uri = iter->data;
+
+ folder = e_mail_session_uri_to_folder_sync (
+ m->session, fi_uri, 0, cancellable, NULL);
+ if (folder != NULL) {
+ vfolder_add_remove_one (m->folders, m->remove, folder, cancellable);
+ g_object_unref (folder);
+ }
+ }
+
+ g_list_free_full (uris, g_free);
+ } else {
+ /* always pick fresh folders - they are
+ * from CamelStore's folders bag anyway */
+ folder = e_mail_session_uri_to_folder_sync (
+ m->session, m->uri, 0, cancellable, error);
+
+ if (folder != NULL) {
+ vfolder_add_remove_one (m->folders, m->remove, folder, cancellable);
+ g_object_unref (folder);
}
- g_object_unref (folder);
}
}
@@ -359,10 +432,11 @@ mail_vfolder_add_folder (CamelStore *store,
CamelService *service;
CamelSession *session;
EFilterRule *rule;
+ EMVFolderRule *vrule;
const gchar *source;
CamelVeeFolder *vf;
CamelProvider *provider;
- GList *folders = NULL;
+ GList *folders = NULL, *folders_include_subfolders = NULL;
gint remote;
gchar *uri;
@@ -395,18 +469,20 @@ mail_vfolder_add_folder (CamelStore *store,
d(printf("invalid rule (%p): rule->name is set to NULL\n", rule));
continue;
}
+
+ vrule = (EMVFolderRule *) rule;
+
/* Don't auto-add any sent/drafts folders etc,
* they must be explictly listed as a source. */
if (rule->source
&& !CAMEL_IS_VEE_STORE (store)
- && ((em_vfolder_rule_get_with ((EMVFolderRule *) rule) == EM_VFOLDER_RULE_WITH_LOCAL && !remote)
- || (em_vfolder_rule_get_with ((EMVFolderRule *) rule) == EM_VFOLDER_RULE_WITH_REMOTE_ACTIVE && remote)
- || (em_vfolder_rule_get_with ((EMVFolderRule *) rule) == EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE)))
+ && ((em_vfolder_rule_get_with (vrule) == EM_VFOLDER_RULE_WITH_LOCAL && !remote)
+ || (em_vfolder_rule_get_with (vrule) == EM_VFOLDER_RULE_WITH_REMOTE_ACTIVE && remote)
+ || (em_vfolder_rule_get_with (vrule) == EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE)))
found = TRUE;
source = NULL;
- while (!found && (source = em_vfolder_rule_next_source (
- (EMVFolderRule *) rule, source))) {
+ while (!found && (source = em_vfolder_rule_next_source (vrule, source))) {
found = e_mail_folder_uri_equal (session, uri, source);
}
@@ -417,7 +493,11 @@ mail_vfolder_add_folder (CamelStore *store,
continue;
}
g_object_ref (vf);
- folders = g_list_prepend (folders, vf);
+
+ if (em_vfolder_rule_source_get_include_subfolders (vrule, uri))
+ folders_include_subfolders = g_list_prepend (folders_include_subfolders, vf);
+ else
+ folders = g_list_prepend (folders, vf);
}
}
@@ -429,6 +509,16 @@ done:
E_MAIL_SESSION (session),
uri, folders, remove);
+ if (folders_include_subfolders) {
+ gchar *exuri = g_strconcat ("*", uri, NULL);
+
+ vfolder_adduri (
+ E_MAIL_SESSION (session),
+ exuri, folders_include_subfolders, remove);
+
+ g_free (exuri);
+ }
+
g_free (uri);
}
@@ -671,10 +761,9 @@ static void context_rule_added (ERuleContext *ctx, EFilterRule *rule, EMailSessi
static void
rule_add_sources (EMailSession *session,
GQueue *queue,
- GList **sources_folderp,
- GList **sources_urip)
+ GList **sources_urip,
+ EMVFolderRule *rule)
{
- GList *sources_folder = *sources_folderp;
GList *sources_uri = *sources_urip;
MailFolderCache *folder_cache;
GList *head, *link;
@@ -688,11 +777,14 @@ rule_add_sources (EMailSession *session,
/* always pick fresh folders - they are
* from CamelStore's folders bag anyway */
if (mail_folder_cache_get_folder_from_uri (folder_cache, uri, NULL)) {
- sources_uri = g_list_append (sources_uri, g_strdup (uri));
+ /* "tag" uris with subfolders with a star prefix */
+ if (!rule || !em_vfolder_rule_source_get_include_subfolders (rule, uri))
+ sources_uri = g_list_prepend (sources_uri, g_strdup (uri));
+ else
+ sources_uri = g_list_prepend (sources_uri, g_strconcat ("*", uri, NULL));
}
}
- *sources_folderp = sources_folder;
*sources_urip = sources_uri;
}
@@ -713,7 +805,6 @@ rule_changed (EFilterRule *rule,
EMailSession *session;
CamelService *service;
GList *sources_uri = NULL;
- GList *sources_folder = NULL;
GString *query;
const gchar *full_name;
@@ -764,7 +855,7 @@ rule_changed (EFilterRule *rule,
/* find any (currently available) folders, and add them to the ones to open */
rule_add_sources (
session, em_vfolder_rule_get_sources ((EMVFolderRule *) rule),
- &sources_folder, &sources_uri);
+ &sources_uri, (EMVFolderRule *) rule);
}
G_LOCK (vfolder);
@@ -778,8 +869,7 @@ rule_changed (EFilterRule *rule,
cache = e_mail_session_get_folder_cache (session);
mail_folder_cache_get_local_folder_uris (cache, &queue);
- rule_add_sources (
- session, &queue, &sources_folder, &sources_uri);
+ rule_add_sources (session, &queue, &sources_uri, NULL);
while (!g_queue_is_empty (&queue))
g_free (g_queue_pop_head (&queue));
@@ -794,8 +884,7 @@ rule_changed (EFilterRule *rule,
cache = e_mail_session_get_folder_cache (session);
mail_folder_cache_get_remote_folder_uris (cache, &queue);
- rule_add_sources (
- session, &queue, &sources_folder, &sources_uri);
+ rule_add_sources (session, &queue, &sources_uri, NULL);
while (!g_queue_is_empty (&queue))
g_free (g_queue_pop_head (&queue));
@@ -806,7 +895,7 @@ rule_changed (EFilterRule *rule,
query = g_string_new("");
e_filter_rule_build_code (rule, query);
- vfolder_setup (session, folder, query->str, sources_uri, sources_folder);
+ vfolder_setup (session, folder, query->str, sources_uri);
g_string_free (query, TRUE);
}