aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libemail-engine/mail-vfolder.c245
-rw-r--r--libemail-utils/em-vfolder-rule.c93
-rw-r--r--libemail-utils/em-vfolder-rule.h12
-rw-r--r--mail/em-vfolder-editor-rule.c76
-rw-r--r--mail/mail-vfolder-ui.c13
5 files changed, 340 insertions, 99 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);
}
diff --git a/libemail-utils/em-vfolder-rule.c b/libemail-utils/em-vfolder-rule.c
index 237c99d5ca..ac77e75ce5 100644
--- a/libemail-utils/em-vfolder-rule.c
+++ b/libemail-utils/em-vfolder-rule.c
@@ -49,6 +49,7 @@ struct _EMVFolderRulePrivate {
em_vfolder_rule_with_t with;
GQueue sources; /* uri's of the source folders */
gboolean autoupdate;
+ GHashTable *include_subfolders;
};
static gint validate (EFilterRule *, EAlert **alert);
@@ -80,6 +81,8 @@ vfolder_rule_finalize (GObject *object)
while ((uri = g_queue_pop_head (&rule->priv->sources)) != NULL)
g_free (uri);
+ g_hash_table_destroy (rule->priv->include_subfolders);
+
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (em_vfolder_rule_parent_class)->finalize (object);
}
@@ -110,11 +113,15 @@ em_vfolder_rule_init (EMVFolderRule *rule)
rule->priv = EM_VFOLDER_RULE_GET_PRIVATE (rule);
rule->priv->with = EM_VFOLDER_RULE_WITH_SPECIFIC;
rule->priv->autoupdate = TRUE;
+ /* it's using pointers from priv::sources, and those
+ included has include_subfolders set to true */
+ rule->priv->include_subfolders = g_hash_table_new (g_direct_hash, g_direct_equal);
+
rule->rule.source = g_strdup ("incoming");
}
EFilterRule *
-em_vfolder_rule_new ()
+em_vfolder_rule_new (void)
{
return g_object_new (
EM_TYPE_VFOLDER_RULE, NULL);
@@ -159,6 +166,7 @@ em_vfolder_rule_remove_source (EMVFolderRule *rule,
found =(gchar *) em_vfolder_rule_find_source (rule, uri);
if (found != NULL) {
g_queue_remove (&rule->priv->sources, found);
+ g_hash_table_remove (rule->priv->include_subfolders, found);
g_free (found);
e_filter_rule_emit_changed (E_FILTER_RULE (rule));
}
@@ -183,6 +191,64 @@ em_vfolder_rule_next_source (EMVFolderRule *rule,
return (link != NULL) ? link->data : NULL;
}
+GQueue *
+em_vfolder_rule_get_sources (EMVFolderRule *rule)
+{
+ g_return_val_if_fail (rule != NULL, NULL);
+
+ return &rule->priv->sources;
+}
+
+static gboolean
+check_queue_has_key (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ EMVFolderRule *rule = user_data;
+
+ g_return_val_if_fail (rule != NULL, FALSE);
+
+ return g_queue_find (&rule->priv->sources, key) == NULL;
+}
+
+void
+em_vfolder_rule_sources_changed (EMVFolderRule *rule)
+{
+ g_return_if_fail (rule != NULL);
+
+ g_hash_table_foreach_remove (rule->priv->include_subfolders,
+ check_queue_has_key, rule);
+}
+
+gboolean
+em_vfolder_rule_source_get_include_subfolders (EMVFolderRule *rule,
+ const gchar *source)
+{
+ g_return_val_if_fail (rule != NULL, FALSE);
+ g_return_val_if_fail (source != NULL, FALSE);
+
+ source = em_vfolder_rule_find_source (rule, source);
+
+ return source && g_hash_table_lookup (rule->priv->include_subfolders, source);
+}
+
+void
+em_vfolder_rule_source_set_include_subfolders (EMVFolderRule *rule,
+ const gchar *source,
+ gboolean include_subfolders)
+{
+ g_return_if_fail (rule != NULL);
+ g_return_if_fail (source != NULL);
+
+ source = em_vfolder_rule_find_source (rule, source);
+ g_return_if_fail (source != NULL);
+
+ if (include_subfolders)
+ g_hash_table_insert (rule->priv->include_subfolders, (gpointer) source, GINT_TO_POINTER (1));
+ else
+ g_hash_table_remove (rule->priv->include_subfolders, (gpointer) source);
+}
+
void
em_vfolder_rule_set_with (EMVFolderRule *rule,
em_vfolder_rule_with_t with)
@@ -200,14 +266,6 @@ em_vfolder_rule_get_with (EMVFolderRule *rule)
return rule->priv->with;
}
-GQueue *
-em_vfolder_rule_get_sources (EMVFolderRule *rule)
-{
- g_return_val_if_fail (rule != NULL, NULL);
-
- return &rule->priv->sources;
-}
-
void
em_vfolder_rule_set_autoupdate (EMVFolderRule *rule,
gboolean autoupdate)
@@ -306,6 +364,8 @@ xml_encode (EFilterRule *fr)
work = xmlNewNode (NULL, (const guchar *) "folder");
xmlSetProp (work, (const guchar *) "uri", (guchar *) uri);
+ xmlSetProp (work, (const guchar *) "include-subfolders", (guchar *)
+ (em_vfolder_rule_source_get_include_subfolders (vr, uri) ? "true" : "false"));
xmlAddChild (set, work);
}
@@ -368,7 +428,17 @@ xml_decode (EFilterRule *fr,
if (!strcmp((gchar *)work->name, "folder")) {
tmp = (gchar *)xmlGetProp(work, (const guchar *)"uri");
if (tmp) {
+ gchar *include_subfolders;
+
g_queue_push_tail (&vr->priv->sources, g_strdup (tmp));
+
+ include_subfolders = (gchar *) xmlGetProp (work, (const guchar *) "include-subfolders");
+ if (include_subfolders) {
+ em_vfolder_rule_source_set_include_subfolders (vr,
+ tmp, g_str_equal (include_subfolders, "true"));
+ xmlFree (include_subfolders);
+ }
+
xmlFree (tmp);
}
}
@@ -394,10 +464,15 @@ rule_copy (EFilterRule *dest,
while ((uri = g_queue_pop_head (&vdest->priv->sources)) != NULL)
g_free (uri);
+ em_vfolder_rule_sources_changed (vdest);
+
head = g_queue_peek_head_link (&vsrc->priv->sources);
for (link = head; link != NULL; link = g_list_next (link)) {
const gchar *uri = link->data;
g_queue_push_tail (&vdest->priv->sources, g_strdup (uri));
+
+ em_vfolder_rule_source_set_include_subfolders (vdest, uri,
+ em_vfolder_rule_source_get_include_subfolders (vsrc, uri));
}
vdest->priv->with = vsrc->priv->with;
diff --git a/libemail-utils/em-vfolder-rule.h b/libemail-utils/em-vfolder-rule.h
index f6dbfa0d03..60f30044b4 100644
--- a/libemail-utils/em-vfolder-rule.h
+++ b/libemail-utils/em-vfolder-rule.h
@@ -71,7 +71,7 @@ struct _EMVFolderRuleClass {
};
GType em_vfolder_rule_get_type (void);
-EFilterRule * em_vfolder_rule_new ();
+EFilterRule * em_vfolder_rule_new (void);
void em_vfolder_rule_add_source (EMVFolderRule *rule,
const gchar *uri);
void em_vfolder_rule_remove_source (EMVFolderRule *rule,
@@ -80,11 +80,19 @@ const gchar * em_vfolder_rule_find_source (EMVFolderRule *rule,
const gchar *uri);
const gchar * em_vfolder_rule_next_source (EMVFolderRule *rule,
const gchar *last);
+GQueue * em_vfolder_rule_get_sources (EMVFolderRule *rule);
+void em_vfolder_rule_sources_changed (EMVFolderRule *rule);
+gboolean em_vfolder_rule_source_get_include_subfolders
+ (EMVFolderRule *rule,
+ const gchar *source);
+void em_vfolder_rule_source_set_include_subfolders
+ (EMVFolderRule *rule,
+ const gchar *source,
+ gboolean include_subfolders);
void em_vfolder_rule_set_with (EMVFolderRule *rule,
em_vfolder_rule_with_t with);
em_vfolder_rule_with_t
em_vfolder_rule_get_with (EMVFolderRule *rule);
-GQueue * em_vfolder_rule_get_sources (EMVFolderRule *rule);
void em_vfolder_rule_set_autoupdate (EMVFolderRule *rule,
gboolean autoupdate);
gboolean em_vfolder_rule_get_autoupdate (EMVFolderRule *rule);
diff --git a/mail/em-vfolder-editor-rule.c b/mail/em-vfolder-editor-rule.c
index b1fdadd1ea..78fbd4624d 100644
--- a/mail/em-vfolder-editor-rule.c
+++ b/mail/em-vfolder-editor-rule.c
@@ -211,7 +211,7 @@ struct _source_data {
ERuleContext *rc;
EMVFolderRule *vr;
GtkListStore *model;
- GtkTreeView *list;
+ GtkTreeView *tree_view;
GtkWidget *source_selector;
GtkWidget *buttons[BUTTON_LAST];
};
@@ -221,7 +221,7 @@ set_sensitive (struct _source_data *data)
{
GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection (data->list);
+ selection = gtk_tree_view_get_selection (data->tree_view);
gtk_widget_set_sensitive (
GTK_WIDGET (data->buttons[BUTTON_ADD]), TRUE);
@@ -262,6 +262,39 @@ autoupdate_toggled_cb (GtkToggleButton *toggle,
}
static void
+include_subfolders_toggled_cb (GtkCellRendererToggle *cell_renderer,
+ const gchar *path_string,
+ struct _source_data *data)
+{
+ GtkTreeModel *model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ gtk_cell_renderer_toggle_set_active (cell_renderer,
+ !gtk_cell_renderer_toggle_get_active (cell_renderer));
+
+ model = gtk_tree_view_get_model (data->tree_view);
+ path = gtk_tree_path_new_from_string (path_string);
+
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ gchar *source = NULL;
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ 2, gtk_cell_renderer_toggle_get_active (cell_renderer),
+ -1);
+
+ gtk_tree_model_get (model, &iter, 1, &source, -1);
+ if (source) {
+ em_vfolder_rule_source_set_include_subfolders (data->vr, source,
+ gtk_cell_renderer_toggle_get_active (cell_renderer));
+ g_free (source);
+ }
+ }
+
+ gtk_tree_path_free (path);
+}
+
+static void
vfr_folder_response (EMFolderSelector *selector,
gint button,
struct _source_data *data)
@@ -282,8 +315,9 @@ vfr_folder_response (EMFolderSelector *selector,
GHashTable *known_uris;
GtkTreeIter iter;
GtkTreeSelection *selection;
+ gboolean changed = FALSE;
- selection = gtk_tree_view_get_selection (data->list);
+ selection = gtk_tree_view_get_selection (data->tree_view);
gtk_tree_selection_unselect_all (selection);
known_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -309,6 +343,7 @@ vfr_folder_response (EMFolderSelector *selector,
g_hash_table_insert (known_uris, g_strdup (uri), GINT_TO_POINTER (1));
+ changed = TRUE;
g_queue_push_tail (em_vfolder_rule_get_sources (data->vr), g_strdup (uri));
markup = e_mail_folder_uri_to_markup (session, uri, NULL);
@@ -322,6 +357,8 @@ vfr_folder_response (EMFolderSelector *selector,
}
g_hash_table_destroy (known_uris);
+ if (changed)
+ em_vfolder_rule_sources_changed (data->vr);
set_sensitive (data);
}
@@ -377,7 +414,7 @@ source_remove (GtkWidget *widget,
gint index = 0, first_selected = -1, removed;
gint n;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->list));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->tree_view));
to_remove = g_hash_table_new (g_direct_hash, g_direct_equal);
source = NULL;
@@ -436,7 +473,7 @@ source_remove (GtkWidget *widget,
gtk_tree_path_append_index (path, index);
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (data->model), &iter, path)) {
gtk_tree_selection_select_iter (selection, &iter);
- gtk_tree_view_set_cursor (data->list, path, NULL, FALSE);
+ gtk_tree_view_set_cursor (data->tree_view, path, NULL, FALSE);
}
gtk_tree_path_free (path);
}
@@ -454,6 +491,7 @@ get_widget (EFilterRule *fr,
GtkWidget *autoupdate;
GtkListStore *model;
GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
struct _source_data *data;
const gchar *source;
gchar *tmp;
@@ -538,13 +576,29 @@ get_widget (EFilterRule *fr,
NULL);
gtk_container_add (GTK_CONTAINER (hgrid), scrolled_window);
- model = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+ model = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
renderer = gtk_cell_renderer_text_new ();
tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE);
gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
-1, "column", renderer, "markup", 0, NULL);
+ renderer = gtk_cell_renderer_toggle_new ();
+ column = gtk_tree_view_column_new_with_attributes (
+ "include subfolders", renderer, "active", 2, NULL);
+ g_signal_connect (renderer, "toggled", G_CALLBACK (include_subfolders_toggled_cb), data);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (renderer),
+ "editable", FALSE,
+ "text", _("include subfolders"),
+ NULL);
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_insert_column (GTK_TREE_VIEW (tree_view), column, -1);
+
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), 0);
+ gtk_tree_view_column_set_expand (column, TRUE);
+
gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view);
vgrid = gtk_grid_new ();
@@ -566,7 +620,7 @@ get_widget (EFilterRule *fr,
gtk_container_add (GTK_CONTAINER (vgrid), data->buttons[BUTTON_ADD]);
gtk_container_add (GTK_CONTAINER (vgrid), data->buttons[BUTTON_REMOVE]);
- data->list = GTK_TREE_VIEW (tree_view);
+ data->tree_view = GTK_TREE_VIEW (tree_view);
data->model = model;
session = em_vfolder_editor_context_get_session (EM_VFOLDER_EDITOR_CONTEXT (rc));
@@ -579,11 +633,15 @@ get_widget (EFilterRule *fr,
CAMEL_SESSION (session), source, NULL);
gtk_list_store_append (data->model, &iter);
- gtk_list_store_set (data->model, &iter, 0, markup, 1, source, -1);
+ gtk_list_store_set (data->model, &iter,
+ 0, markup,
+ 1, source,
+ 2, em_vfolder_rule_source_get_include_subfolders (vr, source),
+ -1);
g_free (markup);
}
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->list));
+ selection = gtk_tree_view_get_selection (data->tree_view);
gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
g_signal_connect (
diff --git a/mail/mail-vfolder-ui.c b/mail/mail-vfolder-ui.c
index 14b55d1d8f..d9b68ad834 100644
--- a/mail/mail-vfolder-ui.c
+++ b/mail/mail-vfolder-ui.c
@@ -256,6 +256,16 @@ vfolder_clone_rule (EMailSession *session,
return rule;
}
+static void
+release_rule_notify_cb (gpointer rule)
+{
+ /* disconnect the "changed" signal */
+ g_signal_handlers_disconnect_by_data (rule,
+ g_object_get_data (rule, "editor-dlg"));
+ g_object_set_data (rule, "editor-dlg", NULL);
+ g_object_unref (rule);
+}
+
/* adds a rule with a gui */
void
vfolder_gui_add_rule (EMVFolderRule *rule)
@@ -283,9 +293,10 @@ vfolder_gui_add_rule (EMVFolderRule *rule)
gtk_window_set_default_size (GTK_WINDOW (gd), 500, 500);
gtk_box_pack_start (GTK_BOX (container), w, TRUE, TRUE, 0);
gtk_widget_show ((GtkWidget *) gd);
+ g_object_set_data (G_OBJECT (rule), "editor-dlg", gd);
g_object_set_data_full (
G_OBJECT (gd), "rule", rule,
- (GDestroyNotify) g_object_unref);
+ release_rule_notify_cb);
g_signal_connect (
rule, "changed",
G_CALLBACK (new_rule_changed_cb), gd);