aboutsummaryrefslogtreecommitdiffstats
path: root/libemail-engine
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-12-10 21:09:59 +0800
committerMatthew Barnes <mbarnes@redhat.com>2012-12-13 03:33:43 +0800
commitd09d8de870b6697c8a8b262e7e077b871a69b315 (patch)
tree3b718882e7a0bb0a996daf2967a033d91714c9b5 /libemail-engine
parentb61331ed03ac1c7a9b8614e25510040b9c60ae02 (diff)
downloadgsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.gz
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.zst
gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.zip
Consolidate base utility libraries into libeutil.
Evolution consists of entirely too many small utility libraries, which increases linking and loading time, places a burden on higher layers of the application (e.g. modules) which has to remember to link to all the small in-tree utility libraries, and makes it difficult to generate API documentation for these utility libraries in one Gtk-Doc module. Merge the following utility libraries under the umbrella of libeutil, and enforce a single-include policy on libeutil so we can reorganize the files as desired without disrupting its pseudo-public API. libemail-utils/libemail-utils.la libevolution-utils/libevolution-utils.la filter/libfilter.la widgets/e-timezone-dialog/libetimezonedialog.la widgets/menus/libmenus.la widgets/misc/libemiscwidgets.la widgets/table/libetable.la widgets/text/libetext.la This also merges libedataserverui from the Evolution-Data-Server module, since Evolution is its only consumer nowadays, and I'd like to make some improvements to those APIs without concern for backward-compatibility. And finally, start a Gtk-Doc module for libeutil. It's going to be a project just getting all the symbols _listed_ much less _documented_. But the skeletal structure is in place and I'm off to a good start.
Diffstat (limited to 'libemail-engine')
-rw-r--r--libemail-engine/Makefile.am22
-rw-r--r--libemail-engine/e-mail-session.c5
-rw-r--r--libemail-engine/e-mail-session.h2
-rw-r--r--libemail-engine/e-mail-utils.c2
-rw-r--r--libemail-engine/em-filter-folder-element.c226
-rw-r--r--libemail-engine/em-filter-folder-element.h74
-rw-r--r--libemail-engine/em-vfolder-context.c110
-rw-r--r--libemail-engine/em-vfolder-context.h70
-rw-r--r--libemail-engine/em-vfolder-rule.c494
-rw-r--r--libemail-engine/em-vfolder-rule.h102
-rw-r--r--libemail-engine/libemail-engine.pc.in2
-rw-r--r--libemail-engine/mail-folder-cache.c2
-rw-r--r--libemail-engine/mail-mt.c663
-rw-r--r--libemail-engine/mail-mt.h125
-rw-r--r--libemail-engine/mail-ops.c2
-rw-r--r--libemail-engine/mail-ops.h2
-rw-r--r--libemail-engine/mail-vfolder.c15
-rw-r--r--libemail-engine/mail-vfolder.h5
18 files changed, 1897 insertions, 26 deletions
diff --git a/libemail-engine/Makefile.am b/libemail-engine/Makefile.am
index 5589fe4e73..55fbef2334 100644
--- a/libemail-engine/Makefile.am
+++ b/libemail-engine/Makefile.am
@@ -18,7 +18,9 @@ libemail_engine_la_CPPFLAGS = \
-I$(top_builddir) \
$(EVOLUTION_DATA_SERVER_CFLAGS) \
$(GNOME_PLATFORM_CFLAGS) \
- -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \
+ $(CHAMPLAIN_CFLAGS) \
+ $(GTKHTML_CFLAGS) \
+ -DEVOLUTION_PRIVDATADIR=\""$(privdatadir)"\" \
$(NULL)
libmailengineincludedir = $(privincludedir)/libemail-engine
@@ -33,11 +35,15 @@ libmailengineinclude_HEADERS = \
e-mail-session.h \
e-mail-store-utils.h \
e-mail-utils.h \
+ em-filter-folder-element.h \
+ em-vfolder-context.h \
+ em-vfolder-rule.h \
mail-config.h \
mail-folder-cache.h \
+ mail-mt.h \
mail-ops.h \
mail-tools.h \
- mail-vfolder.h \
+ mail-vfolder.h \
$(NULL)
libemail_engine_la_SOURCES = \
@@ -51,19 +57,23 @@ libemail_engine_la_SOURCES = \
e-mail-session.c \
e-mail-store-utils.c \
e-mail-utils.c \
+ em-filter-folder-element.c \
+ em-vfolder-context.c \
+ em-vfolder-rule.c \
mail-config.c \
mail-folder-cache.c \
+ mail-mt.c \
mail-ops.c \
mail-tools.c \
- mail-vfolder.c \
+ mail-vfolder.c \
$(NULL)
libemail_engine_la_LIBADD = \
- $(top_builddir)/libemail-utils/libemail-utils.la \
- $(top_builddir)/filter/libfilter.la \
- $(top_builddir)/libevolution-utils/libevolution-utils.la \
+ $(top_builddir)/e-util/libeutil.la \
$(EVOLUTION_DATA_SERVER_LIBS) \
$(GNOME_PLATFORM_LIBS) \
+ $(CHAMPLAIN_LIBS) \
+ $(GTKHTML_LIBS) \
$(NULL)
libemail_engine_la_LDFLAGS = -avoid-version $(NO_UNDEFINED)
diff --git a/libemail-engine/e-mail-session.c b/libemail-engine/e-mail-session.c
index aa3adefd12..18e336a5f4 100644
--- a/libemail-engine/e-mail-session.c
+++ b/libemail-engine/e-mail-session.c
@@ -43,9 +43,10 @@
#endif
#include <libebackend/libebackend.h>
-#include <libedataserverui/libedataserverui.h>
-#include "libemail-utils/mail-mt.h"
+#include "libemail-engine/mail-mt.h"
+
+#include "e-util/e-util.h"
/* This is our hack, not part of libcamel. */
#include "camel-null-store.h"
diff --git a/libemail-engine/e-mail-session.h b/libemail-engine/e-mail-session.h
index bd4b2f6727..9445e0b833 100644
--- a/libemail-engine/e-mail-session.h
+++ b/libemail-engine/e-mail-session.h
@@ -28,8 +28,8 @@
#include <camel/camel.h>
#include <libedataserver/libedataserver.h>
#include <libemail-engine/e-mail-enums.h>
+#include <libemail-engine/em-vfolder-context.h>
#include <libemail-engine/mail-folder-cache.h>
-#include <libemail-utils/em-vfolder-context.h>
/* Standard GObject macros */
#define E_TYPE_MAIL_SESSION \
diff --git a/libemail-engine/e-mail-utils.c b/libemail-engine/e-mail-utils.c
index d1429661b7..33ff0d1aaa 100644
--- a/libemail-engine/e-mail-utils.c
+++ b/libemail-engine/e-mail-utils.c
@@ -39,7 +39,7 @@
#include <glib/gi18n.h>
#include <libebook/libebook.h>
-#include <libemail-utils/mail-mt.h>
+#include <libemail-engine/mail-mt.h>
#include "e-mail-folder-utils.h"
#include "e-mail-session.h"
diff --git a/libemail-engine/em-filter-folder-element.c b/libemail-engine/em-filter-folder-element.c
new file mode 100644
index 0000000000..77569b0309
--- /dev/null
+++ b/libemail-engine/em-filter-folder-element.c
@@ -0,0 +1,226 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "em-filter-folder-element.h"
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#define EM_FILTER_FOLDER_ELEMENT_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), EM_TYPE_FILTER_FOLDER_ELEMENT, EMFilterFolderElementPrivate))
+
+struct _EMFilterFolderElementPrivate {
+ gchar *uri;
+};
+
+G_DEFINE_TYPE (
+ EMFilterFolderElement,
+ em_filter_folder_element,
+ E_TYPE_FILTER_ELEMENT)
+
+static void
+filter_folder_element_finalize (GObject *object)
+{
+ EMFilterFolderElementPrivate *priv;
+
+ priv = EM_FILTER_FOLDER_ELEMENT_GET_PRIVATE (object);
+
+ g_free (priv->uri);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (em_filter_folder_element_parent_class)->finalize (object);
+}
+
+static gboolean
+filter_folder_element_validate (EFilterElement *fe,
+ EAlert **alert)
+{
+ EMFilterFolderElement *ff = (EMFilterFolderElement *) fe;
+
+ g_warn_if_fail (alert == NULL || *alert == NULL);
+
+ if (ff->priv->uri != NULL && *ff->priv->uri != '\0')
+ return TRUE;
+
+ if (alert)
+ *alert = e_alert_new ("mail:no-folder", NULL);
+
+ return FALSE;
+}
+
+static gint
+filter_folder_element_eq (EFilterElement *fe,
+ EFilterElement *cm)
+{
+ return E_FILTER_ELEMENT_CLASS (
+ em_filter_folder_element_parent_class)->eq (fe, cm) &&
+ strcmp (((EMFilterFolderElement *) fe)->priv->uri,
+ ((EMFilterFolderElement *) cm)->priv->uri)== 0;
+}
+
+static xmlNodePtr
+filter_folder_element_xml_encode (EFilterElement *fe)
+{
+ xmlNodePtr value, work;
+ EMFilterFolderElement *ff = (EMFilterFolderElement *) fe;
+
+ value = xmlNewNode (NULL, (xmlChar *) "value");
+ xmlSetProp (value, (xmlChar *) "name", (xmlChar *) fe->name);
+ xmlSetProp (value, (xmlChar *) "type", (xmlChar *) "folder");
+
+ work = xmlNewChild (value, NULL, (xmlChar *) "folder", NULL);
+ xmlSetProp (work, (xmlChar *) "uri", (xmlChar *) ff->priv->uri);
+
+ return value;
+}
+
+static gint
+filter_folder_element_xml_decode (EFilterElement *fe,
+ xmlNodePtr node)
+{
+ EMFilterFolderElement *ff = (EMFilterFolderElement *) fe;
+ xmlNodePtr n;
+
+ xmlFree (fe->name);
+ fe->name = (gchar *) xmlGetProp (node, (xmlChar *) "name");
+
+ n = node->children;
+ while (n) {
+ if (!strcmp ((gchar *) n->name, "folder")) {
+ gchar *uri;
+
+ uri = (gchar *) xmlGetProp (n, (xmlChar *) "uri");
+ g_free (ff->priv->uri);
+ ff->priv->uri = g_strdup (uri);
+ xmlFree (uri);
+ break;
+ }
+ n = n->next;
+ }
+
+ return 0;
+}
+
+static GtkWidget *
+filter_folder_element_get_widget (EFilterElement *fe)
+{
+ GtkWidget *widget;
+
+ widget = E_FILTER_ELEMENT_CLASS (em_filter_folder_element_parent_class)->
+ get_widget (fe);
+
+ return widget;
+}
+
+static void
+filter_folder_element_build_code (EFilterElement *fe,
+ GString *out,
+ EFilterPart *ff)
+{
+ /* We are doing nothing on purpose. */
+}
+
+static void
+filter_folder_element_format_sexp (EFilterElement *fe,
+ GString *out)
+{
+ EMFilterFolderElement *ff = (EMFilterFolderElement *) fe;
+
+ camel_sexp_encode_string (out, ff->priv->uri);
+}
+
+static void
+filter_folder_element_copy_value (EFilterElement *de,
+ EFilterElement *se)
+{
+ if (EM_IS_FILTER_FOLDER_ELEMENT (se)) {
+ em_filter_folder_element_set_uri (
+ EM_FILTER_FOLDER_ELEMENT (de),
+ EM_FILTER_FOLDER_ELEMENT (se)->priv->uri);
+ } else {
+ E_FILTER_ELEMENT_CLASS (
+ em_filter_folder_element_parent_class)->copy_value (de, se);
+ }
+}
+static void
+em_filter_folder_element_class_init (EMFilterFolderElementClass *class)
+{
+ GObjectClass *object_class;
+ EFilterElementClass *filter_element_class;
+
+ g_type_class_add_private (class, sizeof (EMFilterFolderElementPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = filter_folder_element_finalize;
+
+ filter_element_class = E_FILTER_ELEMENT_CLASS (class);
+ filter_element_class->validate = filter_folder_element_validate;
+ filter_element_class->eq = filter_folder_element_eq;
+ filter_element_class->xml_encode = filter_folder_element_xml_encode;
+ filter_element_class->xml_decode = filter_folder_element_xml_decode;
+ filter_element_class->get_widget = filter_folder_element_get_widget;
+ filter_element_class->build_code = filter_folder_element_build_code;
+ filter_element_class->format_sexp = filter_folder_element_format_sexp;
+ filter_element_class->copy_value = filter_folder_element_copy_value;
+}
+
+static void
+em_filter_folder_element_init (EMFilterFolderElement *element)
+{
+ element->priv = EM_FILTER_FOLDER_ELEMENT_GET_PRIVATE (element);
+}
+
+EFilterElement *
+em_filter_folder_element_new ()
+{
+ return g_object_new (
+ EM_TYPE_FILTER_FOLDER_ELEMENT,
+ NULL);
+}
+
+const gchar *
+em_filter_folder_element_get_uri (EMFilterFolderElement *element)
+{
+ g_return_val_if_fail (EM_IS_FILTER_FOLDER_ELEMENT (element), NULL);
+
+ return element->priv->uri;
+}
+
+void
+em_filter_folder_element_set_uri (EMFilterFolderElement *element,
+ const gchar *uri)
+{
+ g_return_if_fail (EM_IS_FILTER_FOLDER_ELEMENT (element));
+
+ g_free (element->priv->uri);
+ element->priv->uri = g_strdup (uri);
+}
+
diff --git a/libemail-engine/em-filter-folder-element.h b/libemail-engine/em-filter-folder-element.h
new file mode 100644
index 0000000000..8c619017a6
--- /dev/null
+++ b/libemail-engine/em-filter-folder-element.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeelementrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef EM_FILTER_FOLDER_ELEMENT_H
+#define EM_FILTER_FOLDER_ELEMENT_H
+
+#include <e-util/e-util.h>
+
+/* Standard GObject macros */
+#define EM_TYPE_FILTER_FOLDER_ELEMENT \
+ (em_filter_folder_element_get_type ())
+#define EM_FILTER_FOLDER_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), EM_TYPE_FILTER_FOLDER_ELEMENT, EMFilterFolderElement))
+#define EM_FILTER_FOLDER_ELEMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), EM_TYPE_FILTER_FOLDER_ELEMENT, EMFilterFolderElementClass))
+#define EM_IS_FILTER_FOLDER_ELEMENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), EM_TYPE_FILTER_FOLDER_ELEMENT))
+#define EM_IS_FILTER_FOLDER_ELEMENT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), EM_TYPE_FILTER_FOLDER_ELEMENT))
+#define EM_FILTER_FOLDER_ELEMENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), EM_TYPE_FILTER_FOLDER_ELEMENT, EMFilterFolderElementClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMFilterFolderElement EMFilterFolderElement;
+typedef struct _EMFilterFolderElementClass EMFilterFolderElementClass;
+typedef struct _EMFilterFolderElementPrivate EMFilterFolderElementPrivate;
+
+struct _EMFilterFolderElement {
+ EFilterElement parent;
+ EMFilterFolderElementPrivate *priv;
+};
+
+struct _EMFilterFolderElementClass {
+ EFilterElementClass parent_class;
+};
+
+GType em_filter_folder_element_get_type (void);
+EFilterElement *em_filter_folder_element_new (void);
+const gchar * em_filter_folder_element_get_uri
+ (EMFilterFolderElement *element);
+void em_filter_folder_element_set_uri
+ (EMFilterFolderElement *element,
+ const gchar *uri);
+
+G_END_DECLS
+
+#endif /* EM_FILTER_FOLDER_ELEMENT_H */
diff --git a/libemail-engine/em-vfolder-context.c b/libemail-engine/em-vfolder-context.c
new file mode 100644
index 0000000000..69b82eb18d
--- /dev/null
+++ b/libemail-engine/em-vfolder-context.c
@@ -0,0 +1,110 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "em-vfolder-context.h"
+
+#include <string.h>
+
+#include "em-filter-folder-element.h"
+#include "em-vfolder-rule.h"
+
+#define EM_VFOLDER_CONTEXT_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), EM_TYPE_VFOLDER_CONTEXT, EMVFolderContextPrivate))
+
+struct _EMVFolderContextPrivate {
+ gint placeholder;
+};
+
+enum {
+ PROP_0,
+ PROP_SESSION
+};
+
+G_DEFINE_TYPE (
+ EMVFolderContext,
+ em_vfolder_context,
+ E_TYPE_RULE_CONTEXT)
+
+static EFilterElement *
+vfolder_context_new_element (ERuleContext *context,
+ const gchar *type)
+{
+ if (strcmp (type, "system-flag") == 0)
+ return e_filter_option_new ();
+
+ if (strcmp (type, "score") == 0)
+ return e_filter_int_new_type ("score", -3, 3);
+
+ if (strcmp (type, "folder") == 0)
+ return em_filter_folder_element_new ();
+
+ /* XXX Legacy type name. Same as "folder" now. */
+ if (strcmp (type, "folder-curi") == 0)
+ return em_filter_folder_element_new ();
+
+ return E_RULE_CONTEXT_CLASS (em_vfolder_context_parent_class)->
+ new_element (context, type);
+}
+
+static void
+em_vfolder_context_class_init (EMVFolderContextClass *class)
+{
+ ERuleContextClass *rule_context_class;
+
+ g_type_class_add_private (class, sizeof (EMVFolderContextPrivate));
+
+ rule_context_class = E_RULE_CONTEXT_CLASS (class);
+ rule_context_class->new_element = vfolder_context_new_element;
+}
+
+static void
+em_vfolder_context_init (EMVFolderContext *context)
+{
+ context->priv = EM_VFOLDER_CONTEXT_GET_PRIVATE (context);
+
+ e_rule_context_add_part_set (
+ E_RULE_CONTEXT (context), "partset", E_TYPE_FILTER_PART,
+ (ERuleContextPartFunc) e_rule_context_add_part,
+ (ERuleContextNextPartFunc) e_rule_context_next_part);
+
+ e_rule_context_add_rule_set (
+ E_RULE_CONTEXT (context), "ruleset", EM_TYPE_VFOLDER_RULE,
+ (ERuleContextRuleFunc) e_rule_context_add_rule,
+ (ERuleContextNextRuleFunc) e_rule_context_next_rule);
+
+ E_RULE_CONTEXT (context)->flags =
+ E_RULE_CONTEXT_THREADING | E_RULE_CONTEXT_GROUPING;
+}
+
+EMVFolderContext *
+em_vfolder_context_new ()
+{
+ return g_object_new (
+ EM_TYPE_VFOLDER_CONTEXT, NULL);
+}
diff --git a/libemail-engine/em-vfolder-context.h b/libemail-engine/em-vfolder-context.h
new file mode 100644
index 0000000000..9e2faf357a
--- /dev/null
+++ b/libemail-engine/em-vfolder-context.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef EM_VFOLDER_CONTEXT_H
+#define EM_VFOLDER_CONTEXT_H
+
+#include <e-util/e-util.h>
+
+/* Standard GObject macros */
+#define EM_TYPE_VFOLDER_CONTEXT \
+ (em_vfolder_context_get_type ())
+#define EM_VFOLDER_CONTEXT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), EM_TYPE_VFOLDER_CONTEXT, EMVFolderContext))
+#define EM_VFOLDER_CONTEXT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), EM_TYPE_VFOLDER_CONTEXT, EMVFolderContextClass))
+#define EM_IS_VFOLDER_CONTEXT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), EM_TYPE_VFOLDER_CONTEXT))
+#define EM_IS_VFOLDER_CONTEXT_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), EM_TYPE_VFOLDER_CONTEXT))
+#define EM_VFOLDER_CONTEXT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), EM_TYPE_VFOLDER_CONTEXT, EMVFolderContextClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMVFolderContext EMVFolderContext;
+typedef struct _EMVFolderContextClass EMVFolderContextClass;
+typedef struct _EMVFolderContextPrivate EMVFolderContextPrivate;
+
+struct _EMVFolderContext {
+ ERuleContext parent;
+ EMVFolderContextPrivate *priv;
+};
+
+struct _EMVFolderContextClass {
+ ERuleContextClass parent_class;
+};
+
+GType em_vfolder_context_get_type (void);
+EMVFolderContext *
+ em_vfolder_context_new (void);
+
+G_END_DECLS
+
+#endif /* EM_VFOLDER_CONTEXT_H */
diff --git a/libemail-engine/em-vfolder-rule.c b/libemail-engine/em-vfolder-rule.c
new file mode 100644
index 0000000000..0d6b07a8ff
--- /dev/null
+++ b/libemail-engine/em-vfolder-rule.c
@@ -0,0 +1,494 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Not Zed <notzed@lostzed.mmc.com.au>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <libemail-engine/e-mail-folder-utils.h>
+
+#include "em-vfolder-context.h"
+#include "em-vfolder-rule.h"
+
+#define EM_VFOLDER_RULE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), EM_TYPE_VFOLDER_RULE, EMVFolderRulePrivate))
+
+#define EM_VFOLDER_RULE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), EM_TYPE_VFOLDER_RULE, EMVFolderRulePrivate))
+
+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);
+static gint vfolder_eq (EFilterRule *fr, EFilterRule *cm);
+static xmlNodePtr xml_encode (EFilterRule *);
+static gint xml_decode (EFilterRule *, xmlNodePtr, ERuleContext *f);
+static void rule_copy (EFilterRule *dest, EFilterRule *src);
+static GtkWidget *get_widget (EFilterRule *fr, ERuleContext *f);
+
+/* DO NOT internationalise these strings */
+static const gchar *with_names[] = {
+ "specific",
+ "local_remote_active",
+ "remote_active",
+ "local"
+};
+
+G_DEFINE_TYPE (
+ EMVFolderRule,
+ em_vfolder_rule,
+ E_TYPE_FILTER_RULE)
+
+static void
+vfolder_rule_finalize (GObject *object)
+{
+ EMVFolderRule *rule = EM_VFOLDER_RULE (object);
+ gchar *uri;
+
+ 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);
+}
+
+static void
+em_vfolder_rule_class_init (EMVFolderRuleClass *class)
+{
+ GObjectClass *object_class;
+ EFilterRuleClass *filter_rule_class;
+
+ g_type_class_add_private (class, sizeof (EMVFolderRulePrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = vfolder_rule_finalize;
+
+ filter_rule_class = E_FILTER_RULE_CLASS (class);
+ filter_rule_class->validate = validate;
+ filter_rule_class->eq = vfolder_eq;
+ filter_rule_class->xml_encode = xml_encode;
+ filter_rule_class->xml_decode = xml_decode;
+ filter_rule_class->copy = rule_copy;
+ filter_rule_class->get_widget = get_widget;
+}
+
+static void
+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 (void)
+{
+ return g_object_new (
+ EM_TYPE_VFOLDER_RULE, NULL);
+}
+
+void
+em_vfolder_rule_add_source (EMVFolderRule *rule,
+ const gchar *uri)
+{
+ g_return_if_fail (EM_IS_VFOLDER_RULE (rule));
+ g_return_if_fail (uri);
+
+ g_queue_push_tail (&rule->priv->sources, g_strdup (uri));
+
+ e_filter_rule_emit_changed (E_FILTER_RULE (rule));
+}
+
+const gchar *
+em_vfolder_rule_find_source (EMVFolderRule *rule,
+ const gchar *uri)
+{
+ GList *link;
+
+ g_return_val_if_fail (EM_IS_VFOLDER_RULE (rule), NULL);
+
+ /* only does a simple string or address comparison, should
+ * probably do a decoded url comparison */
+ link = g_queue_find_custom (
+ &rule->priv->sources, uri, (GCompareFunc) strcmp);
+
+ return (link != NULL) ? link->data : NULL;
+}
+
+void
+em_vfolder_rule_remove_source (EMVFolderRule *rule,
+ const gchar *uri)
+{
+ gchar *found;
+
+ g_return_if_fail (EM_IS_VFOLDER_RULE (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));
+ }
+}
+
+const gchar *
+em_vfolder_rule_next_source (EMVFolderRule *rule,
+ const gchar *last)
+{
+ GList *link;
+
+ if (last == NULL) {
+ link = g_queue_peek_head_link (&rule->priv->sources);
+ } else {
+ link = g_queue_find (&rule->priv->sources, last);
+ if (link == NULL)
+ link = g_queue_peek_head_link (&rule->priv->sources);
+ else
+ link = g_list_next (link);
+ }
+
+ 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)
+{
+ g_return_if_fail (rule != NULL);
+
+ rule->priv->with = with;
+}
+
+em_vfolder_rule_with_t
+em_vfolder_rule_get_with (EMVFolderRule *rule)
+{
+ g_return_val_if_fail (rule != NULL, FALSE);
+
+ return rule->priv->with;
+}
+
+void
+em_vfolder_rule_set_autoupdate (EMVFolderRule *rule,
+ gboolean autoupdate)
+{
+ g_return_if_fail (rule != NULL);
+
+ rule->priv->autoupdate = autoupdate;
+}
+
+gboolean
+em_vfolder_rule_get_autoupdate (EMVFolderRule *rule)
+{
+ g_return_val_if_fail (rule != NULL, EM_VFOLDER_RULE_WITH_SPECIFIC);
+
+ return rule->priv->autoupdate;
+}
+
+static gint
+validate (EFilterRule *fr,
+ EAlert **alert)
+{
+ g_return_val_if_fail (fr != NULL, 0);
+ g_warn_if_fail (alert == NULL || *alert == NULL);
+
+ if (!fr->name || !*fr->name) {
+ if (alert)
+ *alert = e_alert_new ("mail:no-name-vfolder", NULL);
+ return 0;
+ }
+
+ /* We have to have at least one source set in the "specific" case.
+ * Do not translate this string! */
+ if (((EMVFolderRule *) fr)->priv->with == EM_VFOLDER_RULE_WITH_SPECIFIC &&
+ g_queue_is_empty (&((EMVFolderRule *) fr)->priv->sources)) {
+ if (alert)
+ *alert = e_alert_new ("mail:vfolder-no-source", NULL);
+ return 0;
+ }
+
+ return E_FILTER_RULE_CLASS (em_vfolder_rule_parent_class)->validate (fr, alert);
+}
+
+static gint
+queue_eq (GQueue *queue_a,
+ GQueue *queue_b)
+{
+ GList *link_a;
+ GList *link_b;
+ gint truth = TRUE;
+
+ link_a = g_queue_peek_head_link (queue_a);
+ link_b = g_queue_peek_head_link (queue_b);
+
+ while (truth && link_a != NULL && link_b != NULL) {
+ gchar *uri_a = link_a->data;
+ gchar *uri_b = link_b->data;
+
+ truth = (strcmp (uri_a, uri_b)== 0);
+
+ link_a = g_list_next (link_a);
+ link_b = g_list_next (link_b);
+ }
+
+ return truth && link_a == NULL && link_b == NULL;
+}
+
+static gint
+vfolder_eq (EFilterRule *fr,
+ EFilterRule *cm)
+{
+ return E_FILTER_RULE_CLASS (em_vfolder_rule_parent_class)->eq (fr, cm)
+ && queue_eq (
+ &((EMVFolderRule *) fr)->priv->sources,
+ &((EMVFolderRule *) cm)->priv->sources);
+}
+
+static xmlNodePtr
+xml_encode (EFilterRule *fr)
+{
+ EMVFolderRule *vr =(EMVFolderRule *) fr;
+ xmlNodePtr node, set, work;
+ GList *head, *link;
+
+ node = E_FILTER_RULE_CLASS (em_vfolder_rule_parent_class)->xml_encode (fr);
+ g_return_val_if_fail (node != NULL, NULL);
+ g_return_val_if_fail (vr->priv->with < G_N_ELEMENTS (with_names), NULL);
+
+ set = xmlNewNode (NULL, (const guchar *)"sources");
+ xmlAddChild (node, set);
+ xmlSetProp (set, (const guchar *)"with", (guchar *) with_names[vr->priv->with]);
+ xmlSetProp (set, (const guchar *)"autoupdate", (guchar *) (vr->priv->autoupdate ? "true" : "false"));
+
+ head = g_queue_peek_head_link (&vr->priv->sources);
+ for (link = head; link != NULL; link = g_list_next (link)) {
+ const gchar *uri = link->data;
+
+ 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);
+ }
+
+ return node;
+}
+
+static void
+set_with (EMVFolderRule *vr,
+ const gchar *name)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (with_names); i++) {
+ if (!strcmp (name, with_names[i])) {
+ vr->priv->with = i;
+ return;
+ }
+ }
+
+ vr->priv->with = 0;
+}
+
+static gint
+xml_decode (EFilterRule *fr,
+ xmlNodePtr node,
+ ERuleContext *f)
+{
+ xmlNodePtr set, work;
+ gint result;
+ EMVFolderRule *vr =(EMVFolderRule *) fr;
+ gchar *tmp;
+
+ result = E_FILTER_RULE_CLASS (em_vfolder_rule_parent_class)->
+ xml_decode (fr, node, f);
+ if (result != 0)
+ return result;
+
+ /* handle old format file, vfolder source is in filterrule */
+ if (strcmp (fr->source, "incoming")!= 0) {
+ set_with (vr, fr->source);
+ g_free (fr->source);
+ fr->source = g_strdup ("incoming");
+ }
+
+ set = node->children;
+ while (set) {
+ if (!strcmp ((gchar *) set->name, "sources")) {
+ tmp = (gchar *) xmlGetProp (set, (const guchar *)"with");
+ if (tmp) {
+ set_with (vr, tmp);
+ xmlFree (tmp);
+ }
+ tmp = (gchar *) xmlGetProp (set, (const guchar *) "autoupdate");
+ if (tmp) {
+ vr->priv->autoupdate = g_str_equal (tmp, "true");
+ xmlFree (tmp);
+ }
+ work = set->children;
+ while (work) {
+ 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);
+ }
+ }
+ work = work->next;
+ }
+ }
+ set = set->next;
+ }
+ return 0;
+}
+
+static void
+rule_copy (EFilterRule *dest,
+ EFilterRule *src)
+{
+ EMVFolderRule *vdest, *vsrc;
+ GList *head, *link;
+ gchar *uri;
+
+ vdest =(EMVFolderRule *) dest;
+ vsrc =(EMVFolderRule *) src;
+
+ 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;
+ vdest->priv->autoupdate = vsrc->priv->autoupdate;
+
+ E_FILTER_RULE_CLASS (em_vfolder_rule_parent_class)->copy (dest, src);
+}
+
+static GtkWidget *
+get_widget (EFilterRule *fr,
+ ERuleContext *rc)
+{
+ GtkWidget *widget;
+
+ widget = E_FILTER_RULE_CLASS (em_vfolder_rule_parent_class)->
+ get_widget (fr, rc);
+
+ return widget;
+}
diff --git a/libemail-engine/em-vfolder-rule.h b/libemail-engine/em-vfolder-rule.h
new file mode 100644
index 0000000000..312ae175e5
--- /dev/null
+++ b/libemail-engine/em-vfolder-rule.h
@@ -0,0 +1,102 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * NotZed <notzed@ximian.com>
+ * Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef EM_VFOLDER_RULE_H
+#define EM_VFOLDER_RULE_H
+
+#include <e-util/e-util.h>
+
+/* Standard GObject macros */
+#define EM_TYPE_VFOLDER_RULE \
+ (em_vfolder_rule_get_type ())
+#define EM_VFOLDER_RULE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), EM_TYPE_VFOLDER_RULE, EMVFolderRule))
+#define EM_VFOLDER_RULE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), EM_TYPE_VFOLDER_RULE, EMVFolderRuleClass))
+#define EM_IS_VFOLDER_RULE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), EM_TYPE_VFOLDER_RULE))
+#define EM_IS_VFOLDER_RULE_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), EM_TYPE_VFOLDER_RULE))
+#define EM_VFOLDER_RULE_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), EM_TYPE_VFOLDER_RULE, EMVFolderRuleClass))
+
+G_BEGIN_DECLS
+
+/* perhaps should be bits? */
+enum _em_vfolder_rule_with_t {
+ EM_VFOLDER_RULE_WITH_SPECIFIC,
+ EM_VFOLDER_RULE_WITH_LOCAL_REMOTE_ACTIVE,
+ EM_VFOLDER_RULE_WITH_REMOTE_ACTIVE,
+ EM_VFOLDER_RULE_WITH_LOCAL
+};
+
+typedef struct _EMVFolderRule EMVFolderRule;
+typedef struct _EMVFolderRuleClass EMVFolderRuleClass;
+typedef struct _EMVFolderRulePrivate EMVFolderRulePrivate;
+
+typedef enum _em_vfolder_rule_with_t em_vfolder_rule_with_t;
+
+struct _EMVFolderRule {
+ EFilterRule rule;
+ EMVFolderRulePrivate *priv;
+};
+
+struct _EMVFolderRuleClass {
+ EFilterRuleClass parent_class;
+};
+
+GType em_vfolder_rule_get_type (void);
+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,
+ const gchar *uri);
+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);
+void em_vfolder_rule_set_autoupdate (EMVFolderRule *rule,
+ gboolean autoupdate);
+gboolean em_vfolder_rule_get_autoupdate (EMVFolderRule *rule);
+
+G_END_DECLS
+
+#endif /* EM_VFOLDER_RULE_H */
diff --git a/libemail-engine/libemail-engine.pc.in b/libemail-engine/libemail-engine.pc.in
index 2457e0182f..ea5ffab771 100644
--- a/libemail-engine/libemail-engine.pc.in
+++ b/libemail-engine/libemail-engine.pc.in
@@ -11,6 +11,6 @@ privincludedir=@privincludedir@
Name: libemail-engine
Description: Client library for evolution mail
Version: @VERSION@
-Requires: libemail-utils
+Requires: camel-1.2 libedataserver-1.2 libebackend-1.2 gio-2.0
Libs: -L${privlibdir} -lemail-engine
Cflags: -I${privincludedir}
diff --git a/libemail-engine/mail-folder-cache.c b/libemail-engine/mail-folder-cache.c
index 4d82557467..35e620862e 100644
--- a/libemail-engine/mail-folder-cache.c
+++ b/libemail-engine/mail-folder-cache.c
@@ -40,7 +40,7 @@
#include <libedataserver/libedataserver.h>
-#include <libemail-utils/mail-mt.h>
+#include <libemail-engine/mail-mt.h>
#include "mail-folder-cache.h"
#include "e-mail-utils.h"
diff --git a/libemail-engine/mail-mt.c b/libemail-engine/mail-mt.c
new file mode 100644
index 0000000000..baf1476f82
--- /dev/null
+++ b/libemail-engine/mail-mt.c
@@ -0,0 +1,663 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <gtk/gtk.h>
+
+#include <libedataserver/libedataserver.h>
+
+#include "mail-mt.h"
+
+/*#define MALLOC_CHECK*/
+#define d(x)
+
+/* XXX This is a dirty hack on a dirty hack. We really need
+ * to rework or get rid of the functions that use this. */
+const gchar *shell_builtin_backend = "mail";
+
+static guint mail_msg_seq; /* sequence number of each message */
+
+/* Table of active messages. Must hold mail_msg_lock to access. */
+static GHashTable *mail_msg_active_table;
+static GMutex mail_msg_lock;
+static GCond mail_msg_cond;
+
+static MailMsgCreateActivityFunc create_activity = NULL;
+static MailMsgSubmitActivityFunc submit_activity = NULL;
+static MailMsgFreeActivityFunc free_activity = NULL;
+static MailMsgCompleteActivityFunc complete_activity = NULL;
+static MailMsgAlertErrorFunc alert_error = NULL;
+static MailMsgCancelActivityFunc cancel_activity = NULL;
+static MailMsgGetAlertSinkFunc get_alert_sink = NULL;
+
+void
+mail_msg_register_activities (MailMsgCreateActivityFunc acreate,
+ MailMsgSubmitActivityFunc asubmit,
+ MailMsgFreeActivityFunc freeact,
+ MailMsgCompleteActivityFunc comp_act,
+ MailMsgCancelActivityFunc cancel_act,
+ MailMsgAlertErrorFunc ealert,
+ MailMsgGetAlertSinkFunc ealertsink)
+{
+ /* XXX This is an utter hack to keep EActivity out
+ * of EDS and still let Evolution do EActivity. */
+ create_activity = acreate;
+ submit_activity = asubmit;
+ free_activity = freeact;
+ complete_activity = comp_act;
+ cancel_activity = cancel_act;
+ alert_error = ealert;
+ get_alert_sink = ealertsink;
+}
+
+EAlertSink *
+mail_msg_get_alert_sink ()
+{
+ if (get_alert_sink)
+ return get_alert_sink ();
+
+ return NULL;
+}
+
+static void
+mail_msg_cancelled (CamelOperation *operation,
+ gpointer user_data)
+{
+ mail_msg_cancel (GPOINTER_TO_UINT (user_data));
+}
+
+static gboolean
+mail_msg_submit (CamelOperation *cancellable)
+{
+
+ if (submit_activity)
+ submit_activity ((GCancellable *) cancellable);
+ return FALSE;
+}
+
+gpointer
+mail_msg_new (MailMsgInfo *info)
+{
+ MailMsg *msg;
+
+ g_mutex_lock (&mail_msg_lock);
+
+ msg = g_slice_alloc0 (info->size);
+ msg->info = info;
+ msg->ref_count = 1;
+ msg->seq = mail_msg_seq++;
+
+ msg->cancellable = camel_operation_new ();
+
+ if (create_activity)
+ create_activity (msg->cancellable);
+
+ g_signal_connect (
+ msg->cancellable, "cancelled",
+ G_CALLBACK (mail_msg_cancelled),
+ GINT_TO_POINTER (msg->seq));
+
+ g_hash_table_insert (
+ mail_msg_active_table, GINT_TO_POINTER (msg->seq), msg);
+
+ d (printf ("New message %p\n", msg));
+
+ g_mutex_unlock (&mail_msg_lock);
+
+ return msg;
+}
+
+#ifdef MALLOC_CHECK
+#include <mcheck.h>
+
+static void
+checkmem (gpointer p)
+{
+ if (p) {
+ gint status = mprobe (p);
+
+ switch (status) {
+ case MCHECK_HEAD:
+ printf ("Memory underrun at %p\n", p);
+ abort ();
+ case MCHECK_TAIL:
+ printf ("Memory overrun at %p\n", p);
+ abort ();
+ case MCHECK_FREE:
+ printf ("Double free %p\n", p);
+ abort ();
+ }
+ }
+}
+#endif
+
+static gboolean
+mail_msg_free (MailMsg *mail_msg)
+{
+ /* This is an idle callback. */
+
+ if (free_activity)
+ free_activity (mail_msg->cancellable);
+
+ if (mail_msg->cancellable != NULL)
+ g_object_unref (mail_msg->cancellable);
+
+ if (mail_msg->error != NULL)
+ g_error_free (mail_msg->error);
+
+ g_slice_free1 (mail_msg->info->size, mail_msg);
+
+ return FALSE;
+}
+
+gpointer
+mail_msg_ref (gpointer msg)
+{
+ MailMsg *mail_msg = msg;
+
+ g_return_val_if_fail (mail_msg != NULL, msg);
+ g_return_val_if_fail (mail_msg->ref_count > 0, msg);
+
+ g_atomic_int_inc (&mail_msg->ref_count);
+
+ return msg;
+}
+
+void
+mail_msg_unref (gpointer msg)
+{
+ MailMsg *mail_msg = msg;
+
+ g_return_if_fail (mail_msg != NULL);
+ g_return_if_fail (mail_msg->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&mail_msg->ref_count)) {
+
+#ifdef MALLOC_CHECK
+ checkmem (mail_msg);
+ checkmem (mail_msg->cancel);
+ checkmem (mail_msg->priv);
+#endif
+ d (printf ("Free message %p\n", msg));
+
+ if (mail_msg->info->free)
+ mail_msg->info->free (mail_msg);
+
+ g_mutex_lock (&mail_msg_lock);
+
+ g_hash_table_remove (
+ mail_msg_active_table,
+ GINT_TO_POINTER (mail_msg->seq));
+ g_cond_broadcast (&mail_msg_cond);
+
+ g_mutex_unlock (&mail_msg_lock);
+
+ /* Destroy the message from an idle callback
+ * so we know we're in the main loop thread. */
+ g_idle_add ((GSourceFunc) mail_msg_free, mail_msg);
+ }
+}
+
+void
+mail_msg_check_error (gpointer msg)
+{
+ MailMsg *m = msg;
+
+#ifdef MALLOC_CHECK
+ checkmem (m);
+ checkmem (m->cancel);
+ checkmem (m->priv);
+#endif
+
+ if (m->error == NULL)
+ return;
+
+ if (complete_activity)
+ complete_activity (m->cancellable);
+
+ if (g_error_matches (m->error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ if (cancel_activity)
+ cancel_activity (m->cancellable);
+ return;
+ }
+
+ /* XXX Hmm, no explanation of why this is needed. It looks like
+ * a lame hack and will be removed at some point, if only to
+ * reintroduce whatever issue made this necessary so we can
+ * document it in the source code this time. */
+ if (g_error_matches (
+ m->error, CAMEL_FOLDER_ERROR,
+ CAMEL_FOLDER_ERROR_INVALID_UID))
+ return;
+
+ /* FIXME: Submit an error on the dbus */
+ if (alert_error) {
+ gchar *what;
+
+ if (m->info->desc && (what = m->info->desc (m))) {
+ alert_error (m->cancellable, what, m->error->message);
+ g_free (what);
+ } else
+ alert_error (m->cancellable, NULL, m->error->message);
+ }
+}
+
+void
+mail_msg_cancel (guint msgid)
+{
+ MailMsg *msg;
+ GCancellable *cancellable = NULL;
+
+ g_mutex_lock (&mail_msg_lock);
+
+ msg = g_hash_table_lookup (
+ mail_msg_active_table, GINT_TO_POINTER (msgid));
+
+ /* Hold a reference to the GCancellable so it doesn't finalize
+ * itself on us between unlocking the mutex and cancelling. */
+ if (msg != NULL) {
+ cancellable = msg->cancellable;
+ if (g_cancellable_is_cancelled (cancellable))
+ cancellable = NULL;
+ else
+ g_object_ref (cancellable);
+ }
+
+ g_mutex_unlock (&mail_msg_lock);
+
+ if (cancellable != NULL) {
+ g_cancellable_cancel (cancellable);
+ g_object_unref (cancellable);
+ }
+}
+
+gboolean
+mail_msg_active (void)
+{
+ gboolean active;
+
+ g_mutex_lock (&mail_msg_lock);
+ active = g_hash_table_size (mail_msg_active_table) > 0;
+ g_mutex_unlock (&mail_msg_lock);
+
+ return active;
+}
+
+/* **************************************** */
+
+static GHookList cancel_hook_list;
+
+GHook *
+mail_cancel_hook_add (GHookFunc func,
+ gpointer data)
+{
+ GHook *hook;
+
+ g_mutex_lock (&mail_msg_lock);
+
+ if (!cancel_hook_list.is_setup)
+ g_hook_list_init (&cancel_hook_list, sizeof (GHook));
+
+ hook = g_hook_alloc (&cancel_hook_list);
+ hook->func = func;
+ hook->data = data;
+
+ g_hook_append (&cancel_hook_list, hook);
+
+ g_mutex_unlock (&mail_msg_lock);
+
+ return hook;
+}
+
+void
+mail_cancel_hook_remove (GHook *hook)
+{
+ g_mutex_lock (&mail_msg_lock);
+
+ g_return_if_fail (cancel_hook_list.is_setup);
+ g_hook_destroy_link (&cancel_hook_list, hook);
+
+ g_mutex_unlock (&mail_msg_lock);
+}
+
+void
+mail_cancel_all (void)
+{
+ camel_operation_cancel_all ();
+
+ g_mutex_lock (&mail_msg_lock);
+
+ if (cancel_hook_list.is_setup)
+ g_hook_list_invoke (&cancel_hook_list, FALSE);
+
+ g_mutex_unlock (&mail_msg_lock);
+}
+
+static guint idle_source_id = 0;
+G_LOCK_DEFINE_STATIC (idle_source_id);
+static GAsyncQueue *main_loop_queue = NULL;
+static GAsyncQueue *msg_reply_queue = NULL;
+static GThread *main_thread = NULL;
+
+static gboolean
+mail_msg_idle_cb (void)
+{
+ MailMsg *msg;
+
+ g_return_val_if_fail (main_loop_queue != NULL, FALSE);
+ g_return_val_if_fail (msg_reply_queue != NULL, FALSE);
+
+ G_LOCK (idle_source_id);
+ idle_source_id = 0;
+ G_UNLOCK (idle_source_id);
+ /* check the main loop queue */
+ while ((msg = g_async_queue_try_pop (main_loop_queue)) != NULL) {
+ GCancellable *cancellable;
+
+ cancellable = msg->cancellable;
+
+ g_idle_add_full (
+ G_PRIORITY_DEFAULT,
+ (GSourceFunc) mail_msg_submit,
+ g_object_ref (msg->cancellable),
+ (GDestroyNotify) g_object_unref);
+ if (msg->info->exec != NULL)
+ msg->info->exec (msg, cancellable, &msg->error);
+ if (msg->info->done != NULL)
+ msg->info->done (msg);
+ mail_msg_unref (msg);
+ }
+
+ /* check the reply queue */
+ while ((msg = g_async_queue_try_pop (msg_reply_queue)) != NULL) {
+ if (msg->info->done != NULL)
+ msg->info->done (msg);
+ mail_msg_check_error (msg);
+ mail_msg_unref (msg);
+ }
+ return FALSE;
+}
+
+static void
+mail_msg_proxy (MailMsg *msg)
+{
+ GCancellable *cancellable;
+
+ cancellable = msg->cancellable;
+
+ if (msg->info->desc != NULL) {
+ gchar *text = msg->info->desc (msg);
+ camel_operation_push_message (cancellable, "%s", text);
+ g_free (text);
+ }
+
+ g_idle_add_full (
+ G_PRIORITY_DEFAULT,
+ (GSourceFunc) mail_msg_submit,
+ g_object_ref (msg->cancellable),
+ (GDestroyNotify) g_object_unref);
+
+ if (msg->info->exec != NULL)
+ msg->info->exec (msg, cancellable, &msg->error);
+
+ if (msg->info->desc != NULL)
+ camel_operation_pop_message (cancellable);
+
+ g_async_queue_push (msg_reply_queue, msg);
+
+ G_LOCK (idle_source_id);
+ if (idle_source_id == 0)
+ idle_source_id = g_idle_add (
+ (GSourceFunc) mail_msg_idle_cb, NULL);
+ G_UNLOCK (idle_source_id);
+}
+
+void
+mail_msg_init (void)
+{
+ g_mutex_init (&mail_msg_lock);
+ g_cond_init (&mail_msg_cond);
+
+ main_loop_queue = g_async_queue_new ();
+ msg_reply_queue = g_async_queue_new ();
+
+ mail_msg_active_table = g_hash_table_new (NULL, NULL);
+ main_thread = g_thread_self ();
+}
+
+static gint
+mail_msg_compare (const MailMsg *msg1,
+ const MailMsg *msg2)
+{
+ gint priority1 = msg1->priority;
+ gint priority2 = msg2->priority;
+
+ if (priority1 == priority2)
+ return 0;
+
+ return (priority1 < priority2) ? 1 : -1;
+}
+
+static gpointer
+create_thread_pool (gpointer data)
+{
+ GThreadPool *thread_pool;
+ gint max_threads = GPOINTER_TO_INT (data);
+
+ /* once created, run forever */
+ thread_pool = g_thread_pool_new (
+ (GFunc) mail_msg_proxy, NULL, max_threads, FALSE, NULL);
+ g_thread_pool_set_sort_function (
+ thread_pool, (GCompareDataFunc) mail_msg_compare, NULL);
+
+ return thread_pool;
+}
+
+void
+mail_msg_main_loop_push (gpointer msg)
+{
+ g_async_queue_push_sorted (
+ main_loop_queue, msg,
+ (GCompareDataFunc) mail_msg_compare, NULL);
+
+ G_LOCK (idle_source_id);
+ if (idle_source_id == 0)
+ idle_source_id = g_idle_add (
+ (GSourceFunc) mail_msg_idle_cb, NULL);
+ G_UNLOCK (idle_source_id);
+}
+
+void
+mail_msg_unordered_push (gpointer msg)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, (GThreadFunc) create_thread_pool, GINT_TO_POINTER (10));
+
+ g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
+}
+
+void
+mail_msg_fast_ordered_push (gpointer msg)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, (GThreadFunc) create_thread_pool, GINT_TO_POINTER (1));
+
+ g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
+}
+
+void
+mail_msg_slow_ordered_push (gpointer msg)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, (GThreadFunc) create_thread_pool, GINT_TO_POINTER (1));
+
+ g_thread_pool_push ((GThreadPool *) once.retval, msg, NULL);
+}
+
+gboolean
+mail_in_main_thread (void)
+{
+ return (g_thread_self () == main_thread);
+}
+
+/* ********************************************************************** */
+
+struct _call_msg {
+ MailMsg base;
+
+ mail_call_t type;
+ MailMainFunc func;
+ gpointer ret;
+ va_list ap;
+ EFlag *done;
+};
+
+static void
+do_call (struct _call_msg *m,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gpointer p1, *p2, *p3, *p4, *p5;
+ gint i1;
+ va_list ap;
+
+ G_VA_COPY (ap, m->ap);
+
+ switch (m->type) {
+ case MAIL_CALL_p_p:
+ p1 = va_arg (ap, gpointer);
+ m->ret = m->func (p1);
+ break;
+ case MAIL_CALL_p_pp:
+ p1 = va_arg (ap, gpointer);
+ p2 = va_arg (ap, gpointer);
+ m->ret = m->func (p1, p2);
+ break;
+ case MAIL_CALL_p_ppp:
+ p1 = va_arg (ap, gpointer);
+ p2 = va_arg (ap, gpointer);
+ p3 = va_arg (ap, gpointer);
+ m->ret = m->func (p1, p2, p3);
+ break;
+ case MAIL_CALL_p_pppp:
+ p1 = va_arg (ap, gpointer);
+ p2 = va_arg (ap, gpointer);
+ p3 = va_arg (ap, gpointer);
+ p4 = va_arg (ap, gpointer);
+ m->ret = m->func (p1, p2, p3, p4);
+ break;
+ case MAIL_CALL_p_ppppp:
+ p1 = va_arg (ap, gpointer);
+ p2 = va_arg (ap, gpointer);
+ p3 = va_arg (ap, gpointer);
+ p4 = va_arg (ap, gpointer);
+ p5 = va_arg (ap, gpointer);
+ m->ret = m->func (p1, p2, p3, p4, p5);
+ break;
+ case MAIL_CALL_p_ppippp:
+ p1 = va_arg (ap, gpointer);
+ p2 = va_arg (ap, gpointer);
+ i1 = va_arg (ap, gint);
+ p3 = va_arg (ap, gpointer);
+ p4 = va_arg (ap, gpointer);
+ p5 = va_arg (ap, gpointer);
+ m->ret = m->func (p1, p2, i1, p3, p4, p5);
+ break;
+ }
+
+ va_end (ap);
+
+ if (g_cancellable_is_cancelled (cancellable)) {
+ if (cancel_activity)
+ cancel_activity (cancellable);
+ } else {
+ if (complete_activity)
+ complete_activity (cancellable);
+ }
+
+ if (m->done != NULL)
+ e_flag_set (m->done);
+}
+
+static void
+do_free (struct _call_msg *msg)
+{
+ va_end (msg->ap);
+}
+
+static MailMsgInfo mail_call_info = {
+ sizeof (struct _call_msg),
+ (MailMsgDescFunc) NULL,
+ (MailMsgExecFunc) do_call,
+ (MailMsgDoneFunc) NULL,
+ (MailMsgFreeFunc) do_free
+};
+
+gpointer
+mail_call_main (mail_call_t type,
+ MailMainFunc func,
+ ...)
+{
+ GCancellable *cancellable;
+ struct _call_msg *m;
+ gpointer ret;
+ va_list ap;
+
+ va_start (ap, func);
+
+ m = mail_msg_new (&mail_call_info);
+ m->type = type;
+ m->func = func;
+ G_VA_COPY (m->ap, ap);
+
+ cancellable = m->base.cancellable;
+
+ if (mail_in_main_thread ())
+ do_call (m, cancellable, &m->base.error);
+ else {
+ mail_msg_ref (m);
+ m->done = e_flag_new ();
+ mail_msg_main_loop_push (m);
+ e_flag_wait (m->done);
+ e_flag_free (m->done);
+ }
+
+ va_end (ap);
+
+ ret = m->ret;
+ mail_msg_unref (m);
+
+ return ret;
+}
+
+void
+mail_mt_set_backend (gchar *backend)
+{
+ shell_builtin_backend = backend;
+}
+
diff --git a/libemail-engine/mail-mt.h b/libemail-engine/mail-mt.h
new file mode 100644
index 0000000000..03cea96398
--- /dev/null
+++ b/libemail-engine/mail-mt.h
@@ -0,0 +1,125 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef _MAIL_MT
+#define _MAIL_MT
+
+#include <camel/camel.h>
+
+#include <e-util/e-util.h>
+
+typedef struct _MailMsg MailMsg;
+typedef struct _MailMsgInfo MailMsgInfo;
+
+typedef gchar * (*MailMsgDescFunc) (MailMsg *msg);
+typedef void (*MailMsgExecFunc) (MailMsg *msg,
+ GCancellable *cancellable,
+ GError **error);
+typedef void (*MailMsgDoneFunc) (MailMsg *msg);
+typedef void (*MailMsgFreeFunc) (MailMsg *msg);
+typedef void (*MailMsgDispatchFunc) (gpointer msg);
+
+typedef void (*MailMsgCreateActivityFunc) (GCancellable *cancellable);
+typedef void (*MailMsgSubmitActivityFunc) (GCancellable *cancellable);
+typedef void (*MailMsgFreeActivityFunc) (GCancellable *cancellable);
+typedef void (*MailMsgCompleteActivityFunc) (GCancellable *cancellable);
+typedef void (*MailMsgCancelActivityFunc) (GCancellable *cancellable);
+typedef void (*MailMsgAlertErrorFunc) (GCancellable *cancellable,
+ const gchar *what,
+ const gchar *message);
+typedef EAlertSink *
+ (*MailMsgGetAlertSinkFunc) (void);
+
+struct _MailMsg {
+ MailMsgInfo *info;
+ volatile gint ref_count;
+ guint seq; /* seq number for synchronisation */
+ gint priority; /* priority (default = 0) */
+ GCancellable *cancellable;
+ GError *error; /* up to the caller to use this */
+};
+
+struct _MailMsgInfo {
+ gsize size;
+ MailMsgDescFunc desc;
+ MailMsgExecFunc exec;
+ MailMsgDoneFunc done;
+ MailMsgFreeFunc free;
+};
+
+/* Just till we move this out to EDS */
+EAlertSink * mail_msg_get_alert_sink (void);
+
+/* setup ports */
+void mail_msg_init (void);
+void mail_msg_register_activities (MailMsgCreateActivityFunc,
+ MailMsgSubmitActivityFunc,
+ MailMsgFreeActivityFunc,
+ MailMsgCompleteActivityFunc,
+ MailMsgCancelActivityFunc,
+ MailMsgAlertErrorFunc,
+ MailMsgGetAlertSinkFunc);
+
+gboolean mail_in_main_thread (void);
+
+/* allocate a new message */
+gpointer mail_msg_new (MailMsgInfo *info);
+gpointer mail_msg_ref (gpointer msg);
+void mail_msg_unref (gpointer msg);
+void mail_msg_check_error (gpointer msg);
+void mail_msg_cancel (guint msgid);
+gboolean mail_msg_active (void);
+
+/* dispatch a message */
+void mail_msg_main_loop_push (gpointer msg);
+void mail_msg_unordered_push (gpointer msg);
+void mail_msg_fast_ordered_push (gpointer msg);
+void mail_msg_slow_ordered_push (gpointer msg);
+
+/* To implement the stop button */
+GHook * mail_cancel_hook_add (GHookFunc func, gpointer data);
+void mail_cancel_hook_remove (GHook *hook);
+void mail_cancel_all (void);
+
+/* request a string/password */
+gchar *mail_get_password (CamelService *service, const gchar *prompt,
+ gboolean secret, gboolean *cache);
+
+void mail_mt_set_backend (gchar *backend);
+
+/* Call a function in the GUI thread, wait for it to return, type is
+ * the marshaller to use. FIXME This thing is horrible, please put
+ * it out of its misery. */
+typedef enum {
+ MAIL_CALL_p_p,
+ MAIL_CALL_p_pp,
+ MAIL_CALL_p_ppp,
+ MAIL_CALL_p_pppp,
+ MAIL_CALL_p_ppppp,
+ MAIL_CALL_p_ppippp
+} mail_call_t;
+
+typedef gpointer (*MailMainFunc)();
+
+gpointer mail_call_main (mail_call_t type, MailMainFunc func, ...);
+
+#endif /* _MAIL_MT */
diff --git a/libemail-engine/mail-ops.c b/libemail-engine/mail-ops.c
index e2bcaa6894..24fc77253f 100644
--- a/libemail-engine/mail-ops.c
+++ b/libemail-engine/mail-ops.c
@@ -36,7 +36,7 @@
#include <libedataserver/libedataserver.h>
-#include <libemail-utils/mail-mt.h>
+#include <libemail-engine/mail-mt.h>
#include "e-mail-utils.h"
#include "mail-ops.h"
diff --git a/libemail-engine/mail-ops.h b/libemail-engine/mail-ops.h
index 42f3118987..dd115ff601 100644
--- a/libemail-engine/mail-ops.h
+++ b/libemail-engine/mail-ops.h
@@ -27,8 +27,8 @@
G_BEGIN_DECLS
#include <camel/camel.h>
-#include <libemail-utils/mail-mt.h>
#include <libemail-engine/e-mail-session.h>
+#include <libemail-engine/mail-mt.h>
void mail_transfer_messages (EMailSession *session,
CamelFolder *source,
diff --git a/libemail-engine/mail-vfolder.c b/libemail-engine/mail-vfolder.c
index eef4d3899b..b23ce0cf2e 100644
--- a/libemail-engine/mail-vfolder.c
+++ b/libemail-engine/mail-vfolder.c
@@ -24,24 +24,21 @@
#include <config.h>
#endif
-#include <string.h>
+#include "mail-vfolder.h"
+#include <string.h>
#include <glib/gi18n.h>
-#include "libevolution-utils/e-alert-dialog.h"
-
-#include "libemail-utils/mail-mt.h"
-#include "libemail-engine/mail-folder-cache.h"
#include "libemail-engine/e-mail-folder-utils.h"
#include "libemail-engine/e-mail-session.h"
#include "libemail-engine/e-mail-utils.h"
+#include "libemail-engine/em-vfolder-context.h"
+#include "libemail-engine/em-vfolder-rule.h"
+#include "libemail-engine/mail-folder-cache.h"
+#include "libemail-engine/mail-mt.h"
#include "libemail-engine/mail-ops.h"
#include "libemail-engine/mail-tools.h"
-#include <libemail-utils/em-vfolder-context.h>
-#include <libemail-utils/em-vfolder-rule.h>
-#include "mail-vfolder.h"
-
#define d(x) /* (printf("%s:%s: ", G_STRLOC, G_STRFUNC), (x))*/
/* Note: Once we completely move mail to EDS, this context wont be available for UI.
diff --git a/libemail-engine/mail-vfolder.h b/libemail-engine/mail-vfolder.h
index eafd6ba1e1..8732526fef 100644
--- a/libemail-engine/mail-vfolder.h
+++ b/libemail-engine/mail-vfolder.h
@@ -24,10 +24,9 @@
#include <camel/camel.h>
-#include <filter/e-filter-part.h>
-#include <filter/e-filter-rule.h>
+#include <e-util/e-util.h>
#include <libemail-engine/e-mail-session.h>
-#include <libemail-utils/em-vfolder-rule.h>
+#include <libemail-engine/em-vfolder-rule.h>
void vfolder_load_storage (EMailSession *session);