aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-08-29 08:21:54 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-08-30 05:23:20 +0800
commit32f545cdf031ebe3718791f18e8fb6b6141fd081 (patch)
tree980723161c32da855ca91b135318d7fa67dc18c7 /modules
parente8382099228d46ebef684c5384bab6ec710283ce (diff)
downloadgsoc2013-evolution-32f545cdf031ebe3718791f18e8fb6b6141fd081.tar.gz
gsoc2013-evolution-32f545cdf031ebe3718791f18e8fb6b6141fd081.tar.zst
gsoc2013-evolution-32f545cdf031ebe3718791f18e8fb6b6141fd081.zip
Simplify EPlugin loading at startup.
- Require all EPlugin and EPluginHook subtypes be registered before loading plugins. This drastically simplifies the EPlugin/EPluginHook negotiation. - Turn most EPluginHook subtypes into GTypeModules and register their types from an e_module_load() function (does not include shell hooks). - Convert EPluginLib and the Mono and Python bindings to GTypeModules and register their types from an e_module_load() function, and kill EPluginTypeHook.
Diffstat (limited to 'modules')
-rw-r--r--modules/Makefile.am10
-rw-r--r--modules/addressbook/Makefile.am2
-rw-r--r--modules/addressbook/e-book-config-hook.c67
-rw-r--r--modules/addressbook/e-book-config-hook.h33
-rw-r--r--modules/addressbook/e-book-shell-backend.c3
-rw-r--r--modules/addressbook/evolution-module-addressbook.c4
-rw-r--r--modules/calendar/Makefile.am9
-rw-r--r--modules/calendar/e-cal-attachment-handler.c512
-rw-r--r--modules/calendar/e-cal-attachment-handler.h67
-rw-r--r--modules/calendar/e-cal-config-hook.c68
-rw-r--r--modules/calendar/e-cal-config-hook.h33
-rw-r--r--modules/calendar/e-cal-event-hook.c72
-rw-r--r--modules/calendar/e-cal-event-hook.h33
-rw-r--r--modules/calendar/e-cal-shell-backend.c13
-rw-r--r--modules/calendar/evolution-module-calendar.c10
-rw-r--r--modules/mail/Makefile.am10
-rw-r--r--modules/mail/e-attachment-handler-mail.h65
-rw-r--r--modules/mail/e-mail-attachment-handler.c (renamed from modules/mail/e-attachment-handler-mail.c)99
-rw-r--r--modules/mail/e-mail-attachment-handler.h67
-rw-r--r--modules/mail/e-mail-config-hook.c69
-rw-r--r--modules/mail/e-mail-config-hook.h33
-rw-r--r--modules/mail/e-mail-event-hook.c93
-rw-r--r--modules/mail/e-mail-event-hook.h33
-rw-r--r--modules/mail/e-mail-junk-hook.c323
-rw-r--r--modules/mail/e-mail-junk-hook.h66
-rw-r--r--modules/mail/e-mail-shell-backend.c31
-rw-r--r--modules/mail/em-mailer-prefs.c26
-rw-r--r--modules/mail/evolution-module-mail.c12
-rw-r--r--modules/plugin-lib/Makefile.am20
-rw-r--r--modules/plugin-lib/e-plugin-lib.c249
-rw-r--r--modules/plugin-lib/e-plugin-lib.h92
-rw-r--r--modules/plugin-lib/evolution-module-plugin-lib.c41
-rw-r--r--modules/plugin-mono/Camel.cs1278
-rw-r--r--modules/plugin-mono/Evolution.cs158
-rw-r--r--modules/plugin-mono/Makefile.am22
-rw-r--r--modules/plugin-mono/e-plugin-mono.c261
-rw-r--r--modules/plugin-mono/e-plugin-mono.h69
-rw-r--r--modules/plugin-mono/evolution-module-plugin-mono.c41
-rw-r--r--modules/plugin-python/Makefile.am31
-rw-r--r--modules/plugin-python/e-plugin-python.c230
-rw-r--r--modules/plugin-python/e-plugin-python.h70
-rw-r--r--modules/plugin-python/evolution-module-plugin-python.c41
-rw-r--r--modules/plugin-python/example/Makefile.am29
-rw-r--r--modules/plugin-python/example/hello_python.py5
-rw-r--r--modules/plugin-python/example/org-gnome-hello-python-ui.xml16
-rw-r--r--modules/plugin-python/example/org-gnome-hello-python.eplug.xml20
46 files changed, 4364 insertions, 172 deletions
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 5030d2aeb6..f792a4d9ee 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -1,3 +1,11 @@
-SUBDIRS = addressbook calendar mail
+if ENABLE_MONO
+MONO_DIR = plugin-mono
+endif
+
+if ENABLE_PYTHON
+PYTHON_DIR = plugin-python
+endif
+
+SUBDIRS = addressbook calendar mail plugin-lib $(MONO_DIR) $(PYTHON_DIR)
-include $(top_srcdir)/git.mk
diff --git a/modules/addressbook/Makefile.am b/modules/addressbook/Makefile.am
index 5ba744dee6..05b169841e 100644
--- a/modules/addressbook/Makefile.am
+++ b/modules/addressbook/Makefile.am
@@ -34,6 +34,8 @@ libevolution_module_addressbook_la_SOURCES = \
autocompletion-config.h \
eab-composer-util.c \
eab-composer-util.h \
+ e-book-config-hook.c \
+ e-book-config-hook.h \
e-book-shell-backend.c \
e-book-shell-backend.h \
e-book-shell-content.c \
diff --git a/modules/addressbook/e-book-config-hook.c b/modules/addressbook/e-book-config-hook.c
new file mode 100644
index 0000000000..d8c03a5329
--- /dev/null
+++ b/modules/addressbook/e-book-config-hook.c
@@ -0,0 +1,67 @@
+/*
+ * e-book-config-hook.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-book-config-hook.h"
+
+#include "e-util/e-config.h"
+#include "addressbook/gui/widgets/eab-config.h"
+
+static const EConfigHookTargetMask no_masks[] = {
+ { NULL }
+};
+
+static const EConfigHookTargetMap targets[] = {
+ { "source", EAB_CONFIG_TARGET_SOURCE, no_masks },
+ { NULL }
+};
+
+static void
+book_config_hook_class_init (EPluginHookClass *class)
+{
+ gint ii;
+
+ class->id = "org.gnome.evolution.addressbook.config:1.0";
+
+ for (ii = 0; targets[ii].type != NULL; ii++)
+ e_config_hook_class_add_target_map (
+ (EConfigHookClass *) class, &targets[ii]);
+}
+
+void
+e_book_config_hook_register_type (GTypeModule *type_module)
+{
+ const GTypeInfo type_info = {
+ sizeof (EConfigHookClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) book_config_hook_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EConfigHook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ g_type_module_register_type (
+ type_module, e_config_hook_get_type (),
+ "EBookConfigHook", &type_info, 0);
+}
diff --git a/modules/addressbook/e-book-config-hook.h b/modules/addressbook/e-book-config-hook.h
new file mode 100644
index 0000000000..a5d9e06457
--- /dev/null
+++ b/modules/addressbook/e-book-config-hook.h
@@ -0,0 +1,33 @@
+/*
+ * e-book-config-hook.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_BOOK_CONFIG_HOOK_H
+#define E_BOOK_CONFIG_HOOK_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_book_config_hook_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_BOOK_CONFIG_HOOK_H */
diff --git a/modules/addressbook/e-book-shell-backend.c b/modules/addressbook/e-book-shell-backend.c
index 87ac638822..f96cb0dd22 100644
--- a/modules/addressbook/e-book-shell-backend.c
+++ b/modules/addressbook/e-book-shell-backend.c
@@ -39,7 +39,6 @@
#include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
#include "addressbook/importers/evolution-addressbook-importers.h"
-#include "eab-config.h"
#include "addressbook-config.h"
#include "autocompletion-config.h"
@@ -498,8 +497,6 @@ book_shell_backend_constructed (GObject *object)
book_shell_backend_init_importers ();
book_shell_backend_ensure_sources (shell_backend);
- e_plugin_hook_register_type (eab_config_get_type ());
-
g_signal_connect_swapped (
shell, "handle-uri",
G_CALLBACK (book_shell_backend_handle_uri_cb),
diff --git a/modules/addressbook/evolution-module-addressbook.c b/modules/addressbook/evolution-module-addressbook.c
index 3089133e43..73b3634b91 100644
--- a/modules/addressbook/evolution-module-addressbook.c
+++ b/modules/addressbook/evolution-module-addressbook.c
@@ -19,6 +19,8 @@
*
*/
+#include "e-book-config-hook.h"
+
#include "e-book-shell-backend.h"
#include "e-book-shell-content.h"
#include "e-book-shell-sidebar.h"
@@ -33,6 +35,8 @@ e_module_load (GTypeModule *type_module)
{
/* Register dynamically loaded types. */
+ e_book_config_hook_register_type (type_module);
+
e_book_shell_backend_register_type (type_module);
e_book_shell_content_register_type (type_module);
e_book_shell_sidebar_register_type (type_module);
diff --git a/modules/calendar/Makefile.am b/modules/calendar/Makefile.am
index 8f771167d9..490d42a05e 100644
--- a/modules/calendar/Makefile.am
+++ b/modules/calendar/Makefile.am
@@ -10,6 +10,12 @@ module_LTLIBRARIES = \
libevolution_module_calendar_la_SOURCES = \
evolution-module-calendar.c \
+ e-cal-attachment-handler.c \
+ e-cal-attachment-handler.h \
+ e-cal-config-hook.c \
+ e-cal-config-hook.h \
+ e-cal-event-hook.c \
+ e-cal-event-hook.h \
e-cal-shell-backend.c \
e-cal-shell-backend.h \
e-cal-shell-content.c \
@@ -57,9 +63,6 @@ libevolution_module_calendar_la_SOURCES = \
e-task-shell-view-private.c \
e-task-shell-view-private.h
-# Removed from all three
-# $(top_builddir)/a11y/calendar/libevolution-calendar-a11y.la
-
libevolution_module_calendar_la_LIBADD = \
$(top_builddir)/shell/libeshell.la \
$(top_builddir)/calendar/gui/libevolution-calendar.la \
diff --git a/modules/calendar/e-cal-attachment-handler.c b/modules/calendar/e-cal-attachment-handler.c
new file mode 100644
index 0000000000..dd95cc5d08
--- /dev/null
+++ b/modules/calendar/e-cal-attachment-handler.c
@@ -0,0 +1,512 @@
+/*
+ * e-cal-attachment-handler.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-cal-attachment-handler.h"
+
+#include <glib/gi18n.h>
+#include <libical/ical.h>
+#include <libecal/e-cal.h>
+#include <camel/camel-stream-mem.h>
+#include <libedataserverui/e-source-selector.h>
+
+#include "calendar/common/authentication.h"
+
+#define E_CAL_ATTACHMENT_HANDLER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandlerPrivate))
+
+typedef struct _ImportContext ImportContext;
+
+struct _ECalAttachmentHandlerPrivate {
+ gint placeholder;
+};
+
+struct _ImportContext {
+ ECal *client;
+ icalcomponent *component;
+ ECalSourceType source_type;
+};
+
+static gpointer parent_class;
+static GType cal_attachment_handler_type;
+
+static const gchar *ui =
+"<ui>"
+" <popup name='context'>"
+" <placeholder name='custom-actions'>"
+" <menuitem action='import-to-calendar'/>"
+" <menuitem action='import-to-tasks'/>"
+" </placeholder>"
+" </popup>"
+"</ui>";
+
+static icalcomponent *
+attachment_handler_get_component (EAttachment *attachment)
+{
+ CamelDataWrapper *wrapper;
+ CamelMimePart *mime_part;
+ CamelStream *stream;
+ GByteArray *buffer;
+ icalcomponent *component;
+ const gchar *key = "__icalcomponent__";
+
+ component = g_object_get_data (G_OBJECT (attachment), key);
+ if (component != NULL)
+ return component;
+
+ mime_part = e_attachment_get_mime_part (attachment);
+ if (!CAMEL_IS_MIME_PART (mime_part))
+ return NULL;
+
+ buffer = g_byte_array_new ();
+ stream = camel_stream_mem_new ();
+ camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), buffer);
+ wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part));
+ camel_data_wrapper_decode_to_stream (wrapper, stream);
+ camel_object_unref (stream);
+
+ component = e_cal_util_parse_ics_string ((gchar *) buffer->data);
+
+ g_byte_array_free (buffer, TRUE);
+
+ if (component == NULL)
+ return NULL;
+
+ g_object_set_data_full (
+ G_OBJECT (attachment), key, component,
+ (GDestroyNotify) icalcomponent_free);
+
+ return component;
+}
+
+static gboolean
+attachment_handler_update_objects (ECal *client,
+ icalcomponent *component)
+{
+ icalcomponent_kind kind;
+ icalcomponent *vcalendar;
+ gboolean success;
+
+ kind = icalcomponent_isa (component);
+
+ switch (kind) {
+ case ICAL_VTODO_COMPONENT:
+ case ICAL_VEVENT_COMPONENT:
+ vcalendar = e_cal_util_new_top_level ();
+ if (icalcomponent_get_method (component) == ICAL_METHOD_CANCEL)
+ icalcomponent_set_method (vcalendar, ICAL_METHOD_CANCEL);
+ else
+ icalcomponent_set_method (vcalendar, ICAL_METHOD_PUBLISH);
+ icalcomponent_add_component (
+ vcalendar, icalcomponent_new_clone (component));
+ break;
+
+ case ICAL_VCALENDAR_COMPONENT:
+ vcalendar = icalcomponent_new_clone (component);
+ if (!icalcomponent_get_first_property (vcalendar, ICAL_METHOD_PROPERTY))
+ icalcomponent_set_method (vcalendar, ICAL_METHOD_PUBLISH);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ success = e_cal_receive_objects (client, vcalendar, NULL);
+
+ icalcomponent_free (vcalendar);
+
+ return success;
+}
+
+static void
+attachment_handler_import_event (ECal *client,
+ ECalendarStatus status,
+ EAttachment *attachment)
+{
+ icalcomponent *component;
+ icalcomponent *subcomponent;
+ icalcompiter iter;
+
+ /* FIXME Notify the user somehow. */
+ g_return_if_fail (status == E_CALENDAR_STATUS_OK);
+
+ component = attachment_handler_get_component (attachment);
+ g_return_if_fail (component != NULL);
+
+ iter = icalcomponent_begin_component (component, ICAL_ANY_COMPONENT);
+
+ while ((subcomponent = icalcompiter_deref (&iter)) != NULL) {
+ icalcomponent_kind kind;
+
+ kind = icalcomponent_isa (subcomponent);
+ icalcompiter_next (&iter);
+
+ if (kind == ICAL_VEVENT_COMPONENT)
+ continue;
+
+ if (kind == ICAL_VTIMEZONE_COMPONENT)
+ continue;
+
+ icalcomponent_remove_component (component, subcomponent);
+ icalcomponent_free (subcomponent);
+ }
+
+ /* XXX Do something with the return value. */
+ attachment_handler_update_objects (client, component);
+
+ g_object_unref (attachment);
+ g_object_unref (client);
+}
+
+static void
+attachment_handler_import_todo (ECal *client,
+ ECalendarStatus status,
+ EAttachment *attachment)
+{
+ icalcomponent *component;
+ icalcomponent *subcomponent;
+ icalcompiter iter;
+
+ /* FIXME Notify the user somehow. */
+ g_return_if_fail (status == E_CALENDAR_STATUS_OK);
+
+ component = attachment_handler_get_component (attachment);
+ g_return_if_fail (component != NULL);
+
+ iter = icalcomponent_begin_component (component, ICAL_ANY_COMPONENT);
+
+ while ((subcomponent = icalcompiter_deref (&iter)) != NULL) {
+ icalcomponent_kind kind;
+
+ kind = icalcomponent_isa (subcomponent);
+ icalcompiter_next (&iter);
+
+ if (kind == ICAL_VTODO_COMPONENT)
+ continue;
+
+ if (kind == ICAL_VTIMEZONE_COMPONENT)
+ continue;
+
+ icalcomponent_remove_component (component, subcomponent);
+ icalcomponent_free (subcomponent);
+ }
+
+ /* XXX Do something with the return value. */
+ attachment_handler_update_objects (client, component);
+
+ g_object_unref (attachment);
+ g_object_unref (client);
+}
+
+static void
+attachment_handler_row_activated_cb (GtkDialog *dialog)
+{
+ gtk_dialog_response (dialog, GTK_RESPONSE_OK);
+}
+
+static void
+attachment_handler_run_dialog (GtkWindow *parent,
+ EAttachment *attachment,
+ ECalSourceType source_type,
+ const gchar *title)
+{
+ GtkWidget *dialog;
+ GtkWidget *container;
+ GtkWidget *widget;
+ GCallback callback;
+ ESourceSelector *selector;
+ ESourceList *source_list;
+ ESource *source;
+ ECal *client;
+ icalcomponent *component;
+ GError *error = NULL;
+
+ component = attachment_handler_get_component (attachment);
+ g_return_if_fail (component != NULL);
+
+ e_cal_get_sources (&source_list, source_type, &error);
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ source = e_source_list_peek_source_any (source_list);
+ g_return_if_fail (source != NULL);
+
+ dialog = gtk_dialog_new_with_buttons (
+ title, parent, GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
+
+ widget = gtk_button_new_with_mnemonic (_("I_mport"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_icon_name (
+ "stock_mail-import", GTK_ICON_SIZE_MENU));
+ gtk_dialog_add_action_widget (
+ GTK_DIALOG (dialog), widget, GTK_RESPONSE_OK);
+ gtk_widget_show (widget);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 400);
+
+ container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ widget = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (
+ GTK_SCROLLED_WINDOW (widget),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (
+ GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = e_source_selector_new (source_list);
+ selector = E_SOURCE_SELECTOR (widget);
+ e_source_selector_set_primary_selection (selector, source);
+ e_source_selector_show_selection (selector, FALSE);
+ gtk_container_add (GTK_CONTAINER (container), widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "row-activated",
+ G_CALLBACK (attachment_handler_row_activated_cb), dialog);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
+ goto exit;
+
+ source = e_source_selector_peek_primary_selection (selector);
+ if (source == NULL)
+ goto exit;
+
+ client = auth_new_cal_from_source (source, source_type);
+ if (client == NULL)
+ goto exit;
+
+ if (source_type == E_CAL_SOURCE_TYPE_EVENT)
+ callback = G_CALLBACK (attachment_handler_import_event);
+ else if (source_type == E_CAL_SOURCE_TYPE_TODO)
+ callback = G_CALLBACK (attachment_handler_import_todo);
+ else
+ goto exit;
+
+ g_object_ref (attachment);
+ g_signal_connect (client, "cal-opened", callback, attachment);
+ e_cal_open_async (client, FALSE);
+
+exit:
+ gtk_widget_destroy (dialog);
+}
+
+static void
+attachment_handler_import_to_calendar (GtkAction *action,
+ EAttachmentHandler *handler)
+{
+ EAttachment *attachment;
+ EAttachmentView *view;
+ GList *selected;
+ gpointer parent;
+
+ view = e_attachment_handler_get_view (handler);
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (view));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+ selected = e_attachment_view_get_selected_attachments (view);
+ g_return_if_fail (g_list_length (selected) == 1);
+ attachment = E_ATTACHMENT (selected->data);
+
+ attachment_handler_run_dialog (
+ parent, attachment,
+ E_CAL_SOURCE_TYPE_EVENT,
+ _("Select a Calendar"));
+
+ g_object_unref (attachment);
+ g_list_free (selected);
+}
+
+static void
+attachment_handler_import_to_tasks (GtkAction *action,
+ EAttachmentHandler *handler)
+{
+ EAttachment *attachment;
+ EAttachmentView *view;
+ GList *selected;
+ gpointer parent;
+
+ view = e_attachment_handler_get_view (handler);
+
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (view));
+ parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+ selected = e_attachment_view_get_selected_attachments (view);
+ g_return_if_fail (g_list_length (selected) == 1);
+ attachment = E_ATTACHMENT (selected->data);
+
+ attachment_handler_run_dialog (
+ parent, attachment,
+ E_CAL_SOURCE_TYPE_TODO,
+ _("Select a Task List"));
+
+ g_object_unref (attachment);
+ g_list_free (selected);
+}
+
+static GtkActionEntry standard_entries[] = {
+
+ { "import-to-calendar",
+ "stock_mail-import",
+ N_("I_mport to Calendar"),
+ NULL,
+ NULL, /* XXX Add a tooltip! */
+ G_CALLBACK (attachment_handler_import_to_calendar) },
+
+ { "import-to-tasks",
+ "stock_mail-import",
+ N_("I_mport to Tasks"),
+ NULL,
+ NULL, /* XXX Add a tooltip! */
+ G_CALLBACK (attachment_handler_import_to_tasks) }
+};
+
+static void
+cal_attachment_handler_update_actions (EAttachmentView *view)
+{
+ EAttachment *attachment;
+ GtkAction *action;
+ GList *selected;
+ icalcomponent *component;
+ icalcomponent *subcomponent;
+ icalcomponent_kind kind;
+ gboolean is_vevent = FALSE;
+ gboolean is_vtodo = FALSE;
+
+ selected = e_attachment_view_get_selected_attachments (view);
+
+ if (g_list_length (selected) != 1)
+ goto exit;
+
+ attachment = E_ATTACHMENT (selected->data);
+ component = attachment_handler_get_component (attachment);
+
+ if (component == NULL)
+ goto exit;
+
+ subcomponent = icalcomponent_get_inner (component);
+
+ if (subcomponent == NULL)
+ goto exit;
+
+ kind = icalcomponent_isa (subcomponent);
+ is_vevent = (kind == ICAL_VEVENT_COMPONENT);
+ is_vtodo = (kind == ICAL_VTODO_COMPONENT);
+
+exit:
+ action = e_attachment_view_get_action (view, "import-to-calendar");
+ gtk_action_set_visible (action, is_vevent);
+
+ action = e_attachment_view_get_action (view, "import-to-tasks");
+ gtk_action_set_visible (action, is_vtodo);
+
+ g_list_foreach (selected, (GFunc) g_object_unref, NULL);
+ g_list_free (selected);
+}
+
+static void
+cal_attachment_handler_constructed (GObject *object)
+{
+ EAttachmentHandler *handler;
+ EAttachmentView *view;
+ GtkActionGroup *action_group;
+ GtkUIManager *ui_manager;
+ GError *error = NULL;
+
+ handler = E_ATTACHMENT_HANDLER (object);
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ view = e_attachment_handler_get_view (handler);
+
+ action_group = e_attachment_view_add_action_group (view, "calendar");
+ gtk_action_group_add_actions (
+ action_group, standard_entries,
+ G_N_ELEMENTS (standard_entries), handler);
+
+ ui_manager = e_attachment_view_get_ui_manager (view);
+ gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
+
+ if (error != NULL) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_signal_connect (
+ view, "update_actions",
+ G_CALLBACK (cal_attachment_handler_update_actions),
+ NULL);
+}
+
+static void
+cal_attachment_handler_class_init (ECalAttachmentHandlerClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (ECalAttachmentHandlerPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->constructed = cal_attachment_handler_constructed;
+}
+
+static void
+cal_attachment_handler_init (ECalAttachmentHandler *handler)
+{
+ handler->priv = E_CAL_ATTACHMENT_HANDLER_GET_PRIVATE (handler);
+}
+
+GType
+e_cal_attachment_handler_get_type (void)
+{
+ return cal_attachment_handler_type;
+}
+
+void
+e_cal_attachment_handler_register_type (GTypeModule *type_module)
+{
+ static const GTypeInfo type_info = {
+ sizeof (ECalAttachmentHandlerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_attachment_handler_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (ECalAttachmentHandler),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) cal_attachment_handler_init,
+ NULL /* value_table */
+ };
+
+ cal_attachment_handler_type = g_type_module_register_type (
+ type_module, E_TYPE_ATTACHMENT_HANDLER,
+ "ECalAttachmentHandler", &type_info, 0);
+}
diff --git a/modules/calendar/e-cal-attachment-handler.h b/modules/calendar/e-cal-attachment-handler.h
new file mode 100644
index 0000000000..b792fbf765
--- /dev/null
+++ b/modules/calendar/e-cal-attachment-handler.h
@@ -0,0 +1,67 @@
+/*
+ * e-cal-attachment-handler.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_CAL_ATTACHMENT_HANDLER_H
+#define E_CAL_ATTACHMENT_HANDLER_H
+
+#include <misc/e-attachment-handler.h>
+
+/* Standard GObject macros */
+#define E_TYPE_CAL_ATTACHMENT_HANDLER \
+ (e_cal_attachment_handler_get_type ())
+#define E_CAL_ATTACHMENT_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandler))
+#define E_CAL_ATTACHMENT_HANDLER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandlerClass))
+#define E_IS_CAL_ATTACHMENT_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER))
+#define E_IS_CAL_ATTACHMENT_HANDLER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_CAL_ATTACHMENT_HANDLER))
+#define E_CAL_ATTACHMENT_HANDLER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_CAL_ATTACHMENT_HANDLER, ECalAttachmentHandlerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ECalAttachmentHandler ECalAttachmentHandler;
+typedef struct _ECalAttachmentHandlerClass ECalAttachmentHandlerClass;
+typedef struct _ECalAttachmentHandlerPrivate ECalAttachmentHandlerPrivate;
+
+struct _ECalAttachmentHandler {
+ EAttachmentHandler parent;
+ ECalAttachmentHandlerPrivate *priv;
+};
+
+struct _ECalAttachmentHandlerClass {
+ EAttachmentHandlerClass parent_class;
+};
+
+GType e_cal_attachment_handler_get_type (void);
+void e_cal_attachment_handler_register_type
+ (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_CAL_ATTACHMENT_HANDLER_H */
diff --git a/modules/calendar/e-cal-config-hook.c b/modules/calendar/e-cal-config-hook.c
new file mode 100644
index 0000000000..4a0522460c
--- /dev/null
+++ b/modules/calendar/e-cal-config-hook.c
@@ -0,0 +1,68 @@
+/*
+ * e-cal-config-hook.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-cal-config-hook.h"
+
+#include "e-util/e-config.h"
+#include "calendar/gui/e-cal-config.h"
+
+static const EConfigHookTargetMask no_masks[] = {
+ { NULL }
+};
+
+static const EConfigHookTargetMap targets[] = {
+ { "source", EC_CONFIG_TARGET_SOURCE, no_masks },
+ { "prefs", EC_CONFIG_TARGET_PREFS, no_masks },
+ { NULL }
+};
+
+static void
+cal_config_hook_class_init (EPluginHookClass *class)
+{
+ gint ii;
+
+ class->id = "org.gnome.evolution.calendar.config:1.0";
+
+ for (ii = 0; targets[ii].type != NULL; ii++)
+ e_config_hook_class_add_target_map (
+ (EConfigHookClass *) class, &targets[ii]);
+}
+
+void
+e_cal_config_hook_register_type (GTypeModule *type_module)
+{
+ const GTypeInfo type_info = {
+ sizeof (EConfigHookClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_config_hook_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EConfigHook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ g_type_module_register_type (
+ type_module, e_config_hook_get_type (),
+ "ECalConfigHook", &type_info, 0);
+}
diff --git a/modules/calendar/e-cal-config-hook.h b/modules/calendar/e-cal-config-hook.h
new file mode 100644
index 0000000000..a22ec56bbc
--- /dev/null
+++ b/modules/calendar/e-cal-config-hook.h
@@ -0,0 +1,33 @@
+/*
+ * e-cal-config-hook.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_CAL_CONFIG_HOOK_H
+#define E_CAL_CONFIG_HOOK_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_cal_config_hook_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_CAL_CONFIG_HOOK_H */
diff --git a/modules/calendar/e-cal-event-hook.c b/modules/calendar/e-cal-event-hook.c
new file mode 100644
index 0000000000..b263727107
--- /dev/null
+++ b/modules/calendar/e-cal-event-hook.c
@@ -0,0 +1,72 @@
+/*
+ * e-cal-event-hook.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-cal-event-hook.h"
+
+#include "e-util/e-event.h"
+#include "calendar/gui/e-cal-event.h"
+
+static const EEventHookTargetMask masks[] = {
+ { "migration", E_CAL_EVENT_MODULE_MIGRATION },
+ { NULL }
+};
+
+static const EEventHookTargetMap targets[] = {
+ { "module", E_CAL_EVENT_TARGET_BACKEND, masks },
+ { NULL }
+};
+
+static void
+cal_event_hook_class_init (EPluginHookClass *class)
+{
+ EEventHookClass *event_hook_class;
+ gint ii;
+
+ event_hook_class = (EEventHookClass *) class;
+ event_hook_class->event = (EEvent *) e_cal_event_peek ();
+
+ class->id = "org.gnome.evolution.calendar.events:1.0";
+
+ for (ii = 0; targets[ii].type != NULL; ii++)
+ e_event_hook_class_add_target_map (
+ (EEventHookClass *) class, &targets[ii]);
+}
+
+void
+e_cal_event_hook_register_type (GTypeModule *type_module)
+{
+ const GTypeInfo type_info = {
+ sizeof (EEventHookClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_event_hook_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EEventHook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ g_type_module_register_type (
+ type_module, e_event_hook_get_type (),
+ "ECalEventHook", &type_info, 0);
+}
diff --git a/modules/calendar/e-cal-event-hook.h b/modules/calendar/e-cal-event-hook.h
new file mode 100644
index 0000000000..9dde31f900
--- /dev/null
+++ b/modules/calendar/e-cal-event-hook.h
@@ -0,0 +1,33 @@
+/*
+ * e-cal-event-hook.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_CAL_EVENT_HOOK_H
+#define E_CAL_EVENT_HOOK_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_cal_event_hook_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_CAL_EVENT_HOOK_H */
diff --git a/modules/calendar/e-cal-shell-backend.c b/modules/calendar/e-cal-shell-backend.c
index 6d9c74411b..5149574323 100644
--- a/modules/calendar/e-cal-shell-backend.c
+++ b/modules/calendar/e-cal-shell-backend.c
@@ -38,9 +38,6 @@
#include "calendar/common/authentication.h"
#include "calendar/gui/calendar-config.h"
#include "calendar/gui/comp-util.h"
-#include "calendar/gui/e-attachment-handler-calendar.h"
-#include "calendar/gui/e-cal-config.h"
-#include "calendar/gui/e-cal-event.h"
#include "calendar/gui/dialogs/cal-prefs-dialog.h"
#include "calendar/gui/dialogs/calendar-setup.h"
#include "calendar/gui/dialogs/event-editor.h"
@@ -509,13 +506,6 @@ static GtkActionEntry source_entries[] = {
};
static void
-cal_shell_backend_init_hooks (void)
-{
- e_plugin_hook_register_type (e_cal_config_hook_get_type ());
- e_plugin_hook_register_type (e_cal_event_hook_get_type ());
-}
-
-static void
cal_shell_backend_init_importers (void)
{
EImportClass *import_class;
@@ -778,15 +768,12 @@ cal_shell_backend_constructed (GObject *object)
G_CALLBACK (cal_shell_backend_window_created_cb),
shell_backend);
- cal_shell_backend_init_hooks ();
cal_shell_backend_init_importers ();
/* Initialize settings before initializing preferences,
* since the preferences bind to the shell settings. */
e_cal_shell_backend_init_settings (shell);
cal_shell_backend_init_preferences (shell);
-
- e_attachment_handler_calendar_get_type ();
}
static void
diff --git a/modules/calendar/evolution-module-calendar.c b/modules/calendar/evolution-module-calendar.c
index 63bf98ead9..f72e8a97e4 100644
--- a/modules/calendar/evolution-module-calendar.c
+++ b/modules/calendar/evolution-module-calendar.c
@@ -19,6 +19,11 @@
*
*/
+#include "e-cal-attachment-handler.h"
+
+#include "e-cal-config-hook.h"
+#include "e-cal-event-hook.h"
+
#include "e-cal-shell-backend.h"
#include "e-cal-shell-content.h"
#include "e-cal-shell-sidebar.h"
@@ -43,6 +48,11 @@ e_module_load (GTypeModule *type_module)
{
/* Register dynamically loaded types. */
+ e_cal_attachment_handler_register_type (type_module);
+
+ e_cal_config_hook_register_type (type_module);
+ e_cal_event_hook_register_type (type_module);
+
e_cal_shell_backend_register_type (type_module);
e_cal_shell_content_register_type (type_module);
e_cal_shell_sidebar_register_type (type_module);
diff --git a/modules/mail/Makefile.am b/modules/mail/Makefile.am
index 866a137b08..462161843c 100644
--- a/modules/mail/Makefile.am
+++ b/modules/mail/Makefile.am
@@ -12,8 +12,14 @@ module_LTLIBRARIES = libevolution-module-mail.la
libevolution_module_mail_la_SOURCES = \
evolution-module-mail.c \
- e-attachment-handler-mail.c \
- e-attachment-handler-mail.h \
+ e-mail-attachment-handler.c \
+ e-mail-attachment-handler.h \
+ e-mail-config-hook.c \
+ e-mail-config-hook.h \
+ e-mail-event-hook.c \
+ e-mail-event-hook.h \
+ e-mail-junk-hook.c \
+ e-mail-junk-hook.h \
e-mail-shell-backend.c \
e-mail-shell-backend.h \
e-mail-shell-content.c \
diff --git a/modules/mail/e-attachment-handler-mail.h b/modules/mail/e-attachment-handler-mail.h
deleted file mode 100644
index c62ea99cab..0000000000
--- a/modules/mail/e-attachment-handler-mail.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * e-attachment-handler-mail.h
- *
- * 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)
- *
- */
-
-#ifndef E_ATTACHMENT_HANDLER_MAIL_H
-#define E_ATTACHMENT_HANDLER_MAIL_H
-
-#include <widgets/misc/e-attachment-handler.h>
-
-/* Standard GObject macros */
-#define E_TYPE_ATTACHMENT_HANDLER_MAIL \
- (e_attachment_handler_mail_get_type ())
-#define E_ATTACHMENT_HANDLER_MAIL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST \
- ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMail))
-#define E_ATTACHMENT_HANDLER_MAIL_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_CAST \
- ((cls), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailClass))
-#define E_IS_ATTACHMENT_HANDLER_MAIL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE \
- ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL))
-#define E_IS_ATTACHMENT_HANDLER_MAIL_CLASS(cls) \
- (G_TYPE_CHECK_CLASS_TYPE \
- ((cls), E_TYPE_ATTACHMENT_HANDLER_MAIL))
-#define E_ATTACHMENT_HANDLER_MAIL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS \
- ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailClass))
-
-G_BEGIN_DECLS
-
-typedef struct _EAttachmentHandlerMail EAttachmentHandlerMail;
-typedef struct _EAttachmentHandlerMailClass EAttachmentHandlerMailClass;
-typedef struct _EAttachmentHandlerMailPrivate EAttachmentHandlerMailPrivate;
-
-struct _EAttachmentHandlerMail {
- EAttachmentHandler parent;
- EAttachmentHandlerMailPrivate *priv;
-};
-
-struct _EAttachmentHandlerMailClass {
- EAttachmentHandlerClass parent_class;
-};
-
-GType e_attachment_handler_mail_get_type (void);
-
-G_END_DECLS
-
-#endif /* E_ATTACHMENT_HANDLER_MAIL_H */
diff --git a/modules/mail/e-attachment-handler-mail.c b/modules/mail/e-mail-attachment-handler.c
index c17c97d8ca..91fe5d3e5f 100644
--- a/modules/mail/e-attachment-handler-mail.c
+++ b/modules/mail/e-mail-attachment-handler.c
@@ -1,5 +1,5 @@
/*
- * e-attachment-handler-mail.c
+ * e-mail-attachment-handler.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,7 +19,7 @@
*
*/
-#include "e-attachment-handler-mail.h"
+#include "e-mail-attachment-handler.h"
#include <glib/gi18n.h>
#include <camel/camel-folder.h>
@@ -29,15 +29,16 @@
#include "mail/em-composer-utils.h"
#include "mail/mail-tools.h"
-#define E_ATTACHMENT_HANDLER_MAIL_GET_PRIVATE(obj) \
+#define E_MAIL_ATTACHMENT_HANDLER_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_ATTACHMENT_HANDLER_MAIL, EAttachmentHandlerMailPrivate))
+ ((obj), E_TYPE_MAIL_ATTACHMENT_HANDLER, EMailAttachmentHandlerPrivate))
-struct _EAttachmentHandlerMailPrivate {
+struct _EMailAttachmentHandlerPrivate {
gint placeholder;
};
static gpointer parent_class;
+static GType mail_attachment_handler_type;
static const gchar *ui =
"<ui>"
@@ -57,7 +58,7 @@ static GtkTargetEntry target_table[] = {
};
static void
-attachment_handler_mail_forward (GtkAction *action,
+mail_attachment_handler_forward (GtkAction *action,
EAttachmentView *view)
{
EAttachment *attachment;
@@ -79,7 +80,7 @@ attachment_handler_mail_forward (GtkAction *action,
}
static void
-attachment_handler_mail_reply_all (GtkAction *action,
+mail_attachment_handler_reply_all (GtkAction *action,
EAttachmentView *view)
{
EAttachment *attachment;
@@ -103,7 +104,7 @@ attachment_handler_mail_reply_all (GtkAction *action,
}
static void
-attachment_handler_mail_reply_sender (GtkAction *action,
+mail_attachment_handler_reply_sender (GtkAction *action,
EAttachmentView *view)
{
EAttachment *attachment;
@@ -133,25 +134,25 @@ static GtkActionEntry standard_entries[] = {
N_("_Forward"),
NULL,
NULL, /* XXX Add a tooltip! */
- G_CALLBACK (attachment_handler_mail_forward) },
+ G_CALLBACK (mail_attachment_handler_forward) },
{ "mail-reply-all",
"mail-reply-all",
N_("Reply to _All"),
NULL,
NULL, /* XXX Add a tooltip! */
- G_CALLBACK (attachment_handler_mail_reply_all) },
+ G_CALLBACK (mail_attachment_handler_reply_all) },
{ "mail-reply-sender",
"mail-reply-sender",
N_("_Reply to Sender"),
NULL,
NULL, /* XXX Add a tooltip! */
- G_CALLBACK (attachment_handler_mail_reply_sender) }
+ G_CALLBACK (mail_attachment_handler_reply_sender) }
};
static void
-attachment_handler_mail_message_rfc822 (EAttachmentView *view,
+mail_attachment_handler_message_rfc822 (EAttachmentView *view,
GdkDragContext *drag_context,
gint x,
gint y,
@@ -213,7 +214,7 @@ exit:
}
static void
-attachment_handler_mail_x_uid_list (EAttachmentView *view,
+mail_attachment_handler_x_uid_list (EAttachmentView *view,
GdkDragContext *drag_context,
gint x,
gint y,
@@ -380,7 +381,7 @@ exit:
}
static void
-attachment_handler_mail_update_actions (EAttachmentView *view)
+mail_attachment_handler_update_actions (EAttachmentView *view)
{
EAttachment *attachment;
CamelMimePart *mime_part;
@@ -413,7 +414,7 @@ exit:
}
static void
-attachment_handler_mail_constructed (GObject *object)
+mail_attachment_handler_constructed (GObject *object)
{
EAttachmentHandler *handler;
EAttachmentView *view;
@@ -443,28 +444,28 @@ attachment_handler_mail_constructed (GObject *object)
g_signal_connect (
view, "update-actions",
- G_CALLBACK (attachment_handler_mail_update_actions),
+ G_CALLBACK (mail_attachment_handler_update_actions),
NULL);
g_signal_connect (
view, "drag-data-received",
- G_CALLBACK (attachment_handler_mail_message_rfc822),
+ G_CALLBACK (mail_attachment_handler_message_rfc822),
NULL);
g_signal_connect (
view, "drag-data-received",
- G_CALLBACK (attachment_handler_mail_x_uid_list),
+ G_CALLBACK (mail_attachment_handler_x_uid_list),
NULL);
}
static GdkDragAction
-attachment_handler_mail_get_drag_actions (EAttachmentHandler *handler)
+mail_attachment_handler_get_drag_actions (EAttachmentHandler *handler)
{
return GDK_ACTION_COPY;
}
static const GtkTargetEntry *
-attachment_handler_mail_get_target_table (EAttachmentHandler *handler,
+mail_attachment_handler_get_target_table (EAttachmentHandler *handler,
guint *n_targets)
{
if (n_targets != NULL)
@@ -474,51 +475,51 @@ attachment_handler_mail_get_target_table (EAttachmentHandler *handler,
}
static void
-attachment_handler_mail_class_init (EAttachmentHandlerMailClass *class)
+mail_attachment_handler_class_init (EMailAttachmentHandlerClass *class)
{
GObjectClass *object_class;
EAttachmentHandlerClass *handler_class;
parent_class = g_type_class_peek_parent (class);
- g_type_class_add_private (class, sizeof (EAttachmentHandlerMailPrivate));
+ g_type_class_add_private (class, sizeof (EMailAttachmentHandlerPrivate));
object_class = G_OBJECT_CLASS (class);
- object_class->constructed = attachment_handler_mail_constructed;
+ object_class->constructed = mail_attachment_handler_constructed;
handler_class = E_ATTACHMENT_HANDLER_CLASS (class);
- handler_class->get_drag_actions = attachment_handler_mail_get_drag_actions;
- handler_class->get_target_table = attachment_handler_mail_get_target_table;
+ handler_class->get_drag_actions = mail_attachment_handler_get_drag_actions;
+ handler_class->get_target_table = mail_attachment_handler_get_target_table;
}
static void
-attachment_handler_mail_init (EAttachmentHandlerMail *handler)
+mail_attachment_handler_init (EMailAttachmentHandler *handler)
{
- handler->priv = E_ATTACHMENT_HANDLER_MAIL_GET_PRIVATE (handler);
+ handler->priv = E_MAIL_ATTACHMENT_HANDLER_GET_PRIVATE (handler);
}
GType
-e_attachment_handler_mail_get_type (void)
+e_mail_attachment_handler_get_type (void)
{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- static const GTypeInfo type_info = {
- sizeof (EAttachmentHandlerMailClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) attachment_handler_mail_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EAttachmentHandlerMail),
- 0, /* n_preallocs */
- (GInstanceInitFunc) attachment_handler_mail_init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- E_TYPE_ATTACHMENT_HANDLER,
- "EAttachmentHandlerMail", &type_info, 0);
- }
+ return mail_attachment_handler_type;
+}
- return type;
+void
+e_mail_attachment_handler_register_type (GTypeModule *type_module)
+{
+ static const GTypeInfo type_info = {
+ sizeof (EMailAttachmentHandlerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mail_attachment_handler_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailAttachmentHandler),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mail_attachment_handler_init,
+ NULL /* value_table */
+ };
+
+ mail_attachment_handler_type = g_type_module_register_type (
+ type_module, E_TYPE_ATTACHMENT_HANDLER,
+ "EMailAttachmentHandler", &type_info, 0);
}
diff --git a/modules/mail/e-mail-attachment-handler.h b/modules/mail/e-mail-attachment-handler.h
new file mode 100644
index 0000000000..13032b488c
--- /dev/null
+++ b/modules/mail/e-mail-attachment-handler.h
@@ -0,0 +1,67 @@
+/*
+ * e-mail-attachment-handler.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_MAIL_ATTACHMENT_HANDLER_H
+#define E_MAIL_ATTACHMENT_HANDLER_H
+
+#include <widgets/misc/e-attachment-handler.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_ATTACHMENT_HANDLER \
+ (e_mail_attachment_handler_get_type ())
+#define E_MAIL_ATTACHMENT_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_ATTACHMENT_HANDLER, EMailAttachmentHandler))
+#define E_MAIL_ATTACHMENT_HANDLER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_ATTACHMENT_HANDLER, EMailAttachmentHandlerClass))
+#define E_IS_MAIL_ATTACHMENT_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_ATTACHMENT_HANDLER))
+#define E_IS_MAIL_ATTACHMENT_HANDLER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_ATTACHMENT_HANDLER))
+#define E_MAIL_ATTACHMENT_HANDLER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_ATTACHMENT_HANDLER, EMailAttachmentHandlerClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailAttachmentHandler EMailAttachmentHandler;
+typedef struct _EMailAttachmentHandlerClass EMailAttachmentHandlerClass;
+typedef struct _EMailAttachmentHandlerPrivate EMailAttachmentHandlerPrivate;
+
+struct _EMailAttachmentHandler {
+ EAttachmentHandler parent;
+ EMailAttachmentHandlerPrivate *priv;
+};
+
+struct _EMailAttachmentHandlerClass {
+ EAttachmentHandlerClass parent_class;
+};
+
+GType e_mail_attachment_handler_get_type (void);
+void e_mail_attachment_handler_register_type
+ (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_ATTACHMENT_HANDLER_H */
diff --git a/modules/mail/e-mail-config-hook.c b/modules/mail/e-mail-config-hook.c
new file mode 100644
index 0000000000..4b37a6b171
--- /dev/null
+++ b/modules/mail/e-mail-config-hook.c
@@ -0,0 +1,69 @@
+/*
+ * e-mail-config-hook.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-mail-config-hook.h"
+
+#include "e-util/e-config.h"
+#include "mail/em-config.h"
+
+static const EConfigHookTargetMask no_masks[] = {
+ { NULL }
+};
+
+static const EConfigHookTargetMap targets[] = {
+ { "folder", EM_CONFIG_TARGET_FOLDER, no_masks },
+ { "prefs", EM_CONFIG_TARGET_PREFS, no_masks },
+ { "account", EM_CONFIG_TARGET_ACCOUNT, no_masks },
+ { NULL }
+};
+
+static void
+mail_config_hook_class_init (EPluginHookClass *class)
+{
+ gint ii;
+
+ class->id = "org.gnome.evolution.mail.config:1.0";
+
+ for (ii = 0; targets[ii].type != NULL; ii++)
+ e_config_hook_class_add_target_map (
+ (EConfigHookClass *) class, &targets[ii]);
+}
+
+void
+e_mail_config_hook_register_type (GTypeModule *type_module)
+{
+ const GTypeInfo type_info = {
+ sizeof (EConfigHookClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mail_config_hook_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EConfigHook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ g_type_module_register_type (
+ type_module, e_config_hook_get_type (),
+ "EMailConfigHook", &type_info, 0);
+}
diff --git a/modules/mail/e-mail-config-hook.h b/modules/mail/e-mail-config-hook.h
new file mode 100644
index 0000000000..e54ad81815
--- /dev/null
+++ b/modules/mail/e-mail-config-hook.h
@@ -0,0 +1,33 @@
+/*
+ * e-mail-config-hook.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_MAIL_CONFIG_HOOK_H
+#define E_MAIL_CONFIG_HOOK_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_mail_config_hook_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_CONFIG_HOOK_H */
diff --git a/modules/mail/e-mail-event-hook.c b/modules/mail/e-mail-event-hook.c
new file mode 100644
index 0000000000..a6be6d294f
--- /dev/null
+++ b/modules/mail/e-mail-event-hook.c
@@ -0,0 +1,93 @@
+/*
+ * e-mail-event-hook.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-mail-event-hook.h"
+
+#include "e-util/e-event.h"
+#include "mail/em-event.h"
+
+static const EEventHookTargetMask folder_masks[] = {
+ { "newmail", EM_EVENT_FOLDER_NEWMAIL },
+ { NULL }
+};
+
+static const EEventHookTargetMask composer_masks[] = {
+ { "sendoption", EM_EVENT_COMPOSER_SEND_OPTION },
+ { NULL }
+};
+
+static const EEventHookTargetMask message_masks[] = {
+ { "replyall", EM_EVENT_MESSAGE_REPLY_ALL },
+ { "reply", EM_EVENT_MESSAGE_REPLY },
+ { NULL }
+};
+
+static const EEventHookTargetMask send_receive_masks[] = {
+ { "sendreceive", EM_EVENT_SEND_RECEIVE },
+ { NULL }
+};
+
+static const EEventHookTargetMask custom_icon_masks[] = {
+ { "customicon", EM_EVENT_CUSTOM_ICON },
+ { NULL }
+};
+
+static const EEventHookTargetMap targets[] = {
+ { "folder", EM_EVENT_TARGET_FOLDER, folder_masks },
+ { "message", EM_EVENT_TARGET_MESSAGE, message_masks },
+ { "composer", EM_EVENT_TARGET_COMPOSER, composer_masks },
+ { "sendreceive", EM_EVENT_TARGET_SEND_RECEIVE, send_receive_masks },
+ { "customicon", EM_EVENT_TARGET_CUSTOM_ICON, custom_icon_masks },
+ { NULL }
+};
+
+static void
+mail_event_hook_class_init (EPluginHookClass *class)
+{
+ gint ii;
+
+ class->id = "org.gnome.evolution.mail.events:1.0";
+
+ for (ii = 0; targets[ii].type != NULL; ii++)
+ e_event_hook_class_add_target_map (
+ (EEventHookClass *) class, &targets[ii]);
+}
+
+void
+e_mail_event_hook_register_type (GTypeModule *type_module)
+{
+ const GTypeInfo type_info = {
+ sizeof (EEventHookClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mail_event_hook_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EEventHook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ g_type_module_register_type (
+ type_module, e_event_hook_get_type (),
+ "EMailEventHook", &type_info, 0);
+}
diff --git a/modules/mail/e-mail-event-hook.h b/modules/mail/e-mail-event-hook.h
new file mode 100644
index 0000000000..9cad43a0c2
--- /dev/null
+++ b/modules/mail/e-mail-event-hook.h
@@ -0,0 +1,33 @@
+/*
+ * e-mail-event-hook.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_MAIL_EVENT_HOOK_H
+#define E_MAIL_EVENT_HOOK_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_mail_event_hook_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_EVENT_HOOK_H */
diff --git a/modules/mail/e-mail-junk-hook.c b/modules/mail/e-mail-junk-hook.c
new file mode 100644
index 0000000000..2687223af9
--- /dev/null
+++ b/modules/mail/e-mail-junk-hook.c
@@ -0,0 +1,323 @@
+/*
+ * e-mail-junk-hook.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-mail-junk-hook.h"
+
+#include <glib/gi18n.h>
+#include <camel/camel-junk-plugin.h>
+
+#include "e-util/e-error.h"
+#include "mail/em-junk.h"
+#include "mail/em-utils.h"
+#include "mail/mail-session.h"
+
+#define E_MAIL_JUNK_HOOK_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_JUNK_HOOK, EMailJunkHookPrivate))
+
+struct _EMailJunkHookPrivate {
+ EMJunkInterface interface;
+};
+
+struct ErrorData {
+ const gchar *error_message;
+ GError *error;
+};
+
+static gpointer parent_class;
+static GType mail_junk_hook_type;
+
+static gboolean
+mail_junk_hook_idle_cb (struct ErrorData *data)
+{
+ GtkWidget *widget;
+
+ widget = e_error_new (
+ NULL, data->error_message, data->error->message, NULL);
+ em_utils_show_error_silent (widget);
+
+ g_error_free (data->error);
+ g_slice_free (struct ErrorData, data);
+
+ return FALSE;
+}
+
+static void
+mail_junk_hook_error (const gchar *error_message,
+ GError *error)
+{
+ struct ErrorData *data;
+
+ g_return_if_fail (error != NULL);
+
+ data = g_slice_new (struct ErrorData);
+ data->error_message = error_message;
+ data->error = error;
+
+ g_idle_add ((GSourceFunc) mail_junk_hook_idle_cb, data);
+}
+
+static const gchar *
+mail_junk_hook_get_name (CamelJunkPlugin *junk_plugin)
+{
+ EMJunkInterface *interface;
+
+ interface = (EMJunkInterface *) junk_plugin;
+
+ if (!interface->hook->plugin->enabled)
+ return _("None");
+
+ return interface->hook->plugin->name;
+}
+
+static void
+mail_junk_hook_plugin_init (CamelJunkPlugin *junk_plugin)
+{
+ EMJunkInterface *interface;
+ EPluginClass *class;
+
+ interface = (EMJunkInterface *) junk_plugin;
+
+ class = E_PLUGIN_GET_CLASS (interface->hook->plugin);
+ g_return_if_fail (class->enable != NULL);
+
+ class->enable (interface->hook->plugin, 1);
+}
+
+static gboolean
+mail_junk_hook_check_junk (CamelJunkPlugin *junk_plugin,
+ CamelMimeMessage *mime_message)
+{
+ EMJunkTarget target = { mime_message, NULL };
+ EMJunkInterface *interface;
+ gpointer result;
+
+ interface = (EMJunkInterface *) junk_plugin;
+
+ if (!interface->hook->plugin->enabled)
+ return FALSE;
+
+ result = e_plugin_invoke (
+ interface->hook->plugin,
+ interface->check_junk, &target);
+
+ if (target.error != NULL)
+ mail_junk_hook_error ("mail:junk-check-error", target.error);
+
+ return (result != NULL);
+}
+
+static void
+mail_junk_hook_report_junk (CamelJunkPlugin *junk_plugin,
+ CamelMimeMessage *mime_message)
+{
+ EMJunkTarget target = { mime_message, NULL };
+ EMJunkInterface *interface;
+
+ interface = (EMJunkInterface *) junk_plugin;
+
+ if (!interface->hook->plugin->enabled)
+ return;
+
+ e_plugin_invoke (
+ interface->hook->plugin,
+ interface->report_junk, &target);
+
+ if (target.error != NULL)
+ mail_junk_hook_error ("mail:junk-report-error", target.error);
+}
+
+static void
+mail_junk_hook_report_notjunk (CamelJunkPlugin *junk_plugin,
+ CamelMimeMessage *mime_message)
+{
+ EMJunkTarget target = { mime_message, NULL };
+ EMJunkInterface *interface;
+
+ interface = (EMJunkInterface *) junk_plugin;
+
+ if (!interface->hook->plugin->enabled)
+ return;
+
+ e_plugin_invoke (
+ interface->hook->plugin,
+ interface->report_notjunk, &target);
+
+ if (target.error != NULL)
+ mail_junk_hook_error (
+ "mail:junk-not-report-error", target.error);
+}
+
+static void
+mail_junk_hook_commit_reports (CamelJunkPlugin *junk_plugin)
+{
+ EMJunkInterface *interface;
+
+ interface = (EMJunkInterface *) junk_plugin;
+
+ if (!interface->hook->plugin->enabled)
+ return;
+
+ e_plugin_invoke (
+ interface->hook->plugin,
+ interface->commit_reports, NULL);
+}
+
+static void
+mail_junk_hook_finalize (GObject *object)
+{
+ EMailJunkHookPrivate *priv;
+
+ priv = E_MAIL_JUNK_HOOK_GET_PRIVATE (object);
+
+ g_free (priv->interface.check_junk);
+ g_free (priv->interface.report_junk);
+ g_free (priv->interface.report_notjunk);
+ g_free (priv->interface.commit_reports);
+ g_free (priv->interface.validate_binary);
+ g_free (priv->interface.plugin_name);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint
+mail_junk_hook_construct (EPluginHook *hook,
+ EPlugin *plugin,
+ xmlNodePtr node)
+{
+ EMailJunkHookPrivate *priv;
+ gchar *property;
+
+ priv = E_MAIL_JUNK_HOOK_GET_PRIVATE (hook);
+
+ /* Chain up to parent's construct() method. */
+ if (E_PLUGIN_HOOK_CLASS (parent_class)->construct (hook, plugin, node) == -1)
+ return -1;
+
+ if (!plugin->enabled)
+ return -1;
+
+ node = xmlFirstElementChild (node);
+
+ if (node == NULL)
+ return -1;
+
+ if (g_strcmp0 ((gchar *) node->name, "interface") != 0)
+ return -1;
+
+ property = e_plugin_xml_prop (node, "check_junk");
+ priv->interface.check_junk = property;
+
+ property = e_plugin_xml_prop (node, "report_junk");
+ priv->interface.report_junk = property;
+
+ property = e_plugin_xml_prop (node, "report_non_junk");
+ priv->interface.report_notjunk = property;
+
+ property = e_plugin_xml_prop (node, "commit_reports");
+ priv->interface.commit_reports = property;
+
+ property = e_plugin_xml_prop (node, "validate_binary");
+ priv->interface.validate_binary = property;
+
+ property = e_plugin_xml_prop (node, "name");
+ priv->interface.plugin_name = property;
+
+ if (priv->interface.check_junk == NULL)
+ return -1;
+
+ if (priv->interface.report_junk == NULL)
+ return -1;
+
+ if (priv->interface.report_notjunk == NULL)
+ return -1;
+
+ if (priv->interface.commit_reports == NULL)
+ return -1;
+
+ mail_session_add_junk_plugin (
+ priv->interface.plugin_name, &priv->interface.camel);
+
+ return 0;
+}
+
+static void
+mail_junk_hook_class_init (EMailJunkHookClass *class)
+{
+ GObjectClass *object_class;
+ EPluginHookClass *plugin_hook_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EMailJunkHookPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = mail_junk_hook_finalize;
+
+ plugin_hook_class = E_PLUGIN_HOOK_CLASS (class);
+ plugin_hook_class->construct = mail_junk_hook_construct;
+ plugin_hook_class->id = "org.gnome.evolution.mail.junk:1.0";
+}
+
+static void
+mail_junk_hook_init (EMailJunkHook *mail_junk_hook)
+{
+ EMJunkInterface *interface;
+
+ mail_junk_hook->priv = E_MAIL_JUNK_HOOK_GET_PRIVATE (mail_junk_hook);
+
+ interface = &mail_junk_hook->priv->interface;
+ interface->camel.get_name = mail_junk_hook_get_name;
+ interface->camel.api_version = 1;
+ interface->camel.check_junk = mail_junk_hook_check_junk;
+ interface->camel.report_junk = mail_junk_hook_report_junk;
+ interface->camel.report_notjunk = mail_junk_hook_report_notjunk;
+ interface->camel.commit_reports = mail_junk_hook_commit_reports;
+ interface->camel.init = mail_junk_hook_plugin_init;
+ interface->hook = E_PLUGIN_HOOK (mail_junk_hook);
+}
+
+GType
+e_mail_junk_hook_get_type (void)
+{
+ return mail_junk_hook_type;
+}
+
+void
+e_mail_junk_hook_register_type (GTypeModule *type_module)
+{
+ const GTypeInfo type_info = {
+ sizeof (EMailJunkHookClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mail_junk_hook_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailJunkHook),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mail_junk_hook_init,
+ NULL /* value_table */
+ };
+
+ mail_junk_hook_type = g_type_module_register_type (
+ type_module, E_TYPE_PLUGIN_HOOK,
+ "EMailJunkHook", &type_info, 0);
+}
diff --git a/modules/mail/e-mail-junk-hook.h b/modules/mail/e-mail-junk-hook.h
new file mode 100644
index 0000000000..f5882e66b3
--- /dev/null
+++ b/modules/mail/e-mail-junk-hook.h
@@ -0,0 +1,66 @@
+/*
+ * e-mail-junk-hook.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_MAIL_JUNK_HOOK_H
+#define E_MAIL_JUNK_HOOK_H
+
+#include <e-util/e-plugin.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_JUNK_HOOK \
+ (e_mail_junk_hook_get_type ())
+#define E_MAIL_JUNK_HOOK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_JUNK_HOOK, EMailJunkHook))
+#define E_MAIL_JUNK_HOOK_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_JUNK_HOOK, EMailJunkHookClass))
+#define E_IS_MAIL_JUNK_HOOK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_JUNK_HOOK))
+#define E_IS_MAIL_JUNK_HOOK_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_JUNK_HOOK))
+#define E_MAIL_JUNK_HOOK_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_JUNK_HOOK, EMailJunkHookClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailJunkHook EMailJunkHook;
+typedef struct _EMailJunkHookClass EMailJunkHookClass;
+typedef struct _EMailJunkHookPrivate EMailJunkHookPrivate;
+
+struct _EMailJunkHook {
+ EPluginHook parent;
+ EMailJunkHookPrivate *priv;
+};
+
+struct _EMailJunkHookClass {
+ EPluginHookClass parent_class;
+};
+
+GType e_mail_junk_hook_get_type (void);
+void e_mail_junk_hook_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_MAIL_JUNK_HOOK_H */
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index 2d6e1a9779..fd1e7263c4 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -42,7 +42,6 @@
#include "e-mail-shell-sidebar.h"
#include "e-mail-shell-view.h"
-#include "e-attachment-handler-mail.h"
#include "e-mail-browser.h"
#include "e-mail-local.h"
#include "e-mail-reader.h"
@@ -51,12 +50,9 @@
#include "em-account-prefs.h"
#include "em-composer-prefs.h"
#include "em-composer-utils.h"
-#include "em-config.h"
-#include "em-event.h"
#include "em-folder-utils.h"
#include "em-format-hook.h"
#include "em-format-html-display.h"
-#include "em-junk-hook.h"
#include "em-mailer-prefs.h"
#include "em-network-prefs.h"
#include "em-utils.h"
@@ -85,22 +81,6 @@ static GType mail_shell_backend_type;
extern gint camel_application_is_exiting;
static void
-mail_shell_backend_init_hooks (void)
-{
- e_plugin_hook_register_type (em_config_hook_get_type ());
- e_plugin_hook_register_type (em_event_hook_get_type ());
- e_plugin_hook_register_type (em_junk_hook_get_type ());
-
- /* EMFormat classes must be registered before EMFormatHook. */
- em_format_hook_register_type (em_format_get_type ());
- em_format_hook_register_type (em_format_html_get_type ());
- em_format_hook_register_type (em_format_html_display_get_type ());
- e_plugin_hook_register_type (em_format_hook_get_type ());
-
- em_junk_hook_register_type (emj_get_type ());
-}
-
-static void
mail_shell_backend_init_importers (void)
{
EImportClass *import_class;
@@ -812,10 +792,15 @@ mail_shell_backend_constructed (GObject *object)
/* This also initializes Camel, so it needs to happen early. */
mail_session_init (shell_backend);
- mail_shell_backend_init_hooks ();
- mail_shell_backend_init_importers ();
+ /* Register format types for EMFormatHook. */
+ em_format_hook_register_type (em_format_get_type ());
+ em_format_hook_register_type (em_format_html_get_type ());
+ em_format_hook_register_type (em_format_html_display_get_type ());
+
+ /* Register plugin hook types. */
+ em_format_hook_get_type ();
- e_attachment_handler_mail_get_type ();
+ mail_shell_backend_init_importers ();
g_signal_connect (
shell, "notify::online",
diff --git a/modules/mail/em-mailer-prefs.c b/modules/mail/em-mailer-prefs.c
index e2c956e0ff..621dae4ce5 100644
--- a/modules/mail/em-mailer-prefs.c
+++ b/modules/mail/em-mailer-prefs.c
@@ -47,7 +47,7 @@
#include "e-mail-label-manager.h"
#include "mail-config.h"
-#include "em-junk-hook.h"
+#include "em-junk.h"
#include "em-config.h"
#include "mail-session.h"
@@ -710,17 +710,17 @@ junk_plugin_changed (GtkWidget *combo, EMMailerPrefs *prefs)
gconf_client_set_string (prefs->gconf, "/apps/evolution/mail/junk/default_plugin", def_plugin, NULL);
while (plugins) {
- struct _EMJunkHookItem *item = plugins->data;;
+ EMJunkInterface *iface = plugins->data;
- if (item->plugin_name && def_plugin && !strcmp (item->plugin_name, def_plugin)) {
+ if (iface->plugin_name && def_plugin && !strcmp (iface->plugin_name, def_plugin)) {
gboolean status;
- session->junk_plugin = CAMEL_JUNK_PLUGIN (&(item->csp));
- status = e_plugin_invoke (item->hook->hook.plugin, item->validate_binary, NULL) != NULL;
+ session->junk_plugin = CAMEL_JUNK_PLUGIN (&iface->camel);
+ status = e_plugin_invoke (iface->hook->plugin, iface->validate_binary, NULL) != NULL;
if ((gboolean)status == TRUE) {
gchar *text, *html;
gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-info", GTK_ICON_SIZE_MENU);
- text = g_strdup_printf (_("%s plugin is available and the binary is installed."), item->plugin_name);
+ text = g_strdup_printf (_("%s plugin is available and the binary is installed."), iface->plugin_name);
html = g_strdup_printf ("<i>%s</i>", text);
gtk_label_set_markup (prefs->plugin_status, html);
g_free (html);
@@ -728,7 +728,7 @@ junk_plugin_changed (GtkWidget *combo, EMMailerPrefs *prefs)
} else {
gchar *text, *html;
gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-warning", GTK_ICON_SIZE_MENU);
- text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), item->plugin_name);
+ text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), iface->plugin_name);
html = g_strdup_printf ("<i>%s</i>", text);
gtk_label_set_markup (prefs->plugin_status, html);
g_free (html);
@@ -761,20 +761,20 @@ junk_plugin_setup (GtkWidget *combo, EMMailerPrefs *prefs)
}
while (plugins) {
- struct _EMJunkHookItem *item = plugins->data;;
+ EMJunkInterface *iface = plugins->data;
- gtk_combo_box_append_text (GTK_COMBO_BOX (combo), item->plugin_name);
- if (!def_set && pdefault && item->plugin_name && !strcmp(pdefault, item->plugin_name)) {
+ gtk_combo_box_append_text (GTK_COMBO_BOX (combo), iface->plugin_name);
+ if (!def_set && pdefault && iface->plugin_name && !strcmp(pdefault, iface->plugin_name)) {
gboolean status;
def_set = TRUE;
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index);
- status = e_plugin_invoke (item->hook->hook.plugin, item->validate_binary, NULL) != NULL;
+ status = e_plugin_invoke (iface->hook->plugin, iface->validate_binary, NULL) != NULL;
if (status) {
gchar *text, *html;
gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-info", GTK_ICON_SIZE_MENU);
/* May be a better text */
- text = g_strdup_printf (_("%s plugin is available and the binary is installed."), item->plugin_name);
+ text = g_strdup_printf (_("%s plugin is available and the binary is installed."), iface->plugin_name);
html = g_strdup_printf ("<i>%s</i>", text);
gtk_label_set_markup (prefs->plugin_status, html);
g_free (html);
@@ -783,7 +783,7 @@ junk_plugin_setup (GtkWidget *combo, EMMailerPrefs *prefs)
gchar *text, *html;
gtk_image_set_from_stock (prefs->plugin_image, "gtk-dialog-warning", GTK_ICON_SIZE_MENU);
/* May be a better text */
- text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), item->plugin_name);
+ text = g_strdup_printf (_("%s plugin is not available. Please check whether the package is installed."), iface->plugin_name);
html = g_strdup_printf ("<i>%s</i>", text);
gtk_label_set_markup (prefs->plugin_status, html);
g_free (html);
diff --git a/modules/mail/evolution-module-mail.c b/modules/mail/evolution-module-mail.c
index 97bc953c41..1bb58c7742 100644
--- a/modules/mail/evolution-module-mail.c
+++ b/modules/mail/evolution-module-mail.c
@@ -19,6 +19,12 @@
*
*/
+#include "e-mail-attachment-handler.h"
+
+#include "e-mail-config-hook.h"
+#include "e-mail-event-hook.h"
+#include "e-mail-junk-hook.h"
+
#include "e-mail-shell-backend.h"
#include "e-mail-shell-content.h"
#include "e-mail-shell-sidebar.h"
@@ -34,6 +40,12 @@ e_module_load (GTypeModule *type_module)
{
/* Register dynamically loaded types. */
+ e_mail_attachment_handler_register_type (type_module);
+
+ e_mail_config_hook_register_type (type_module);
+ e_mail_event_hook_register_type (type_module);
+ e_mail_junk_hook_register_type (type_module);
+
e_mail_shell_backend_register_type (type_module);
e_mail_shell_content_register_type (type_module);
e_mail_shell_sidebar_register_type (type_module);
diff --git a/modules/plugin-lib/Makefile.am b/modules/plugin-lib/Makefile.am
new file mode 100644
index 0000000000..cce60902fa
--- /dev/null
+++ b/modules/plugin-lib/Makefile.am
@@ -0,0 +1,20 @@
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"evolution-plugin-lib\" \
+ -I$(top_srcdir) \
+ $(E_UTIL_CFLAGS)
+
+module_LTLIBRARIES = libevolution-module-plugin-lib.la
+
+libevolution_module_plugin_lib_la_SOURCES = \
+ evolution-module-plugin-lib.c \
+ e-plugin-lib.c \
+ e-plugin-lib.h
+
+libevolution_module_plugin_lib_la_LIBADD = \
+ $(top_builddir)/e-util/libeutil.la \
+ $(E_UTIL_LIBS)
+
+libevolution_module_plugin_lib_la_LDFLAGS = \
+ -module -avoid-version $(NO_UNDEFINED)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/plugin-lib/e-plugin-lib.c b/modules/plugin-lib/e-plugin-lib.c
new file mode 100644
index 0000000000..c7a0233bb3
--- /dev/null
+++ b/modules/plugin-lib/e-plugin-lib.c
@@ -0,0 +1,249 @@
+/*
+ * e-plugin-lib.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-plugin-lib.h"
+
+#include <string.h>
+
+static gpointer parent_class;
+static GType plugin_lib_type;
+
+/* TODO:
+ We need some way to manage lifecycle.
+ We need some way to manage state.
+
+ Maybe just the g module init method will do, or we could add
+ another which returns context.
+
+ There is also the question of per-instance context, e.g. for config
+ pages.
+*/
+
+static gint
+plugin_lib_loadmodule (EPlugin *plugin)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (plugin);
+ EPluginLibEnableFunc enable;
+
+ if (plugin_lib->module != NULL)
+ return 0;
+
+ if (plugin_lib->location == NULL) {
+ g_warning ("Location not set in plugin '%s'", plugin->name);
+ return -1;
+ }
+
+ if ((plugin_lib->module = g_module_open (plugin_lib->location, 0)) == NULL) {
+ g_warning ("can't load plugin '%s': %s", plugin_lib->location, g_module_error ());
+ return -1;
+ }
+
+ if (g_module_symbol (plugin_lib->module, "e_plugin_lib_enable", (gpointer)&enable)) {
+ if (enable (plugin_lib, TRUE) != 0) {
+ plugin->enabled = FALSE;
+ g_module_close (plugin_lib->module);
+ plugin_lib->module = NULL;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static gpointer
+plugin_lib_invoke (EPlugin *plugin, const gchar *name, gpointer data)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (plugin);
+ EPluginLibFunc cb;
+
+ if (!plugin->enabled) {
+ g_warning ("trying to invoke '%s' on disabled plugin '%s'", name, plugin->id);
+ return NULL;
+ }
+
+ if (plugin_lib_loadmodule (plugin) != 0)
+ return NULL;
+
+ if (!g_module_symbol (plugin_lib->module, name, (gpointer)&cb)) {
+ g_warning ("Cannot resolve symbol '%s' in plugin '%s' (not exported?)", name, plugin_lib->location);
+ return NULL;
+ }
+
+ return cb (plugin_lib, data);
+}
+
+static gpointer
+plugin_lib_get_symbol (EPlugin *plugin, const gchar *name)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (plugin);
+ gpointer symbol;
+
+ if (plugin_lib_loadmodule (plugin) != 0)
+ return NULL;
+
+ if (!g_module_symbol (plugin_lib->module, name, &symbol))
+ return NULL;
+
+ return symbol;
+}
+
+static gint
+plugin_lib_construct (EPlugin *plugin, xmlNodePtr root)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (plugin);
+
+ /* Set the location before chaining up, as some EPluginHooks
+ * will cause the module to load during hook construction. */
+
+ plugin_lib->location = e_plugin_xml_prop (root, "location");
+
+ if (plugin_lib->location == NULL) {
+ g_warning ("Library plugin '%s' has no location", plugin->id);
+ return -1;
+ }
+#ifdef G_OS_WIN32
+ {
+ gchar *mapped_location =
+ e_util_rplugin_libace_prefix (EVOLUTION_PREFIX,
+ e_util_get_prefix (),
+ plugin_lib->location);
+ g_free (plugin_lib->location);
+ plugin_lib->location = mapped_location;
+ }
+#endif
+
+ /* Chain up to parent's construct() method. */
+ if (E_PLUGIN_CLASS (parent_class)->construct (plugin, root) == -1)
+ return -1;
+
+ /* If we're enabled, check for the load-on-startup property */
+ if (plugin->enabled) {
+ xmlChar *tmp;
+
+ tmp = xmlGetProp (root, (const guchar *)"load-on-startup");
+ if (tmp) {
+ if (plugin_lib_loadmodule (plugin) != 0) {
+ xmlFree (tmp);
+ return -1;
+ }
+ xmlFree (tmp);
+ }
+ }
+
+ return 0;
+}
+
+static GtkWidget *
+plugin_lib_get_configure_widget (EPlugin *plugin)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (plugin);
+ EPluginLibGetConfigureWidgetFunc get_configure_widget;
+
+ if (plugin_lib_loadmodule (plugin) != 0) {
+ return NULL;
+ }
+
+ if (g_module_symbol (plugin_lib->module, "e_plugin_lib_get_configure_widget", (gpointer)&get_configure_widget)) {
+ return (GtkWidget*) get_configure_widget (plugin_lib);
+ }
+ return NULL;
+}
+
+static void
+plugin_lib_enable (EPlugin *plugin, gint state)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (plugin);
+ EPluginLibEnableFunc enable;
+
+ E_PLUGIN_CLASS (parent_class)->enable (plugin, state);
+
+ /* if we're disabling and it isn't loaded, nothing to do */
+ if (!state && plugin_lib->module == NULL)
+ return;
+
+ /* this will noop if we're disabling since we tested it above */
+ if (plugin_lib_loadmodule (plugin) != 0)
+ return;
+
+ if (g_module_symbol (plugin_lib->module, "e_plugin_lib_enable", (gpointer) &enable)) {
+ if (enable (plugin_lib, state) != 0)
+ return;
+ }
+}
+
+static void
+plugin_lib_finalize (GObject *object)
+{
+ EPluginLib *plugin_lib = E_PLUGIN_LIB (object);
+
+ g_free (plugin_lib->location);
+
+ if (plugin_lib->module)
+ g_module_close (plugin_lib->module);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+plugin_lib_class_init (EPluginClass *class)
+{
+ GObjectClass *object_class;
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = plugin_lib_finalize;
+
+ class->construct = plugin_lib_construct;
+ class->invoke = plugin_lib_invoke;
+ class->get_symbol = plugin_lib_get_symbol;
+ class->enable = plugin_lib_enable;
+ class->get_configure_widget = plugin_lib_get_configure_widget;
+ class->type = "shlib";
+}
+
+GType
+e_plugin_lib_get_type (void)
+{
+ return plugin_lib_type;
+}
+
+void
+e_plugin_lib_register_type (GTypeModule *type_module)
+{
+ static const GTypeInfo type_info = {
+ sizeof (EPluginLibClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) plugin_lib_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPluginLib),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ NULL /* value_table */
+ };
+
+ plugin_lib_type = g_type_module_register_type (
+ type_module, E_TYPE_PLUGIN,
+ "EPluginLib", &type_info, 0);
+}
diff --git a/modules/plugin-lib/e-plugin-lib.h b/modules/plugin-lib/e-plugin-lib.h
new file mode 100644
index 0000000000..b485d9625e
--- /dev/null
+++ b/modules/plugin-lib/e-plugin-lib.h
@@ -0,0 +1,92 @@
+/*
+ * e-plugin-lib.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_PLUGIN_LIB_H
+#define E_PLUGIN_LIB_H
+
+#include <gmodule.h>
+#include <e-util/e-plugin.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PLUGIN_LIB \
+ (e_plugin_lib_get_type ())
+#define E_PLUGIN_LIB(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_PLUGIN_LIB, EPluginLib))
+#define E_PLUGIN_LIB_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_PLUGIN_LIB, EPluginLibClass))
+#define E_IS_PLUGIN_LIB(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_PLUGIN_LIB))
+#define E_IS_PLUGIN_LIB_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_PLUGIN_LIB))
+#define E_PLUGIN_LIB_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_PLUGIN_LIB, EPluginLibClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPluginLib EPluginLib;
+typedef struct _EPluginLibClass EPluginLibClass;
+
+/* The callback signature used for epluginlib methods */
+typedef gpointer (*EPluginLibFunc) (EPluginLib *ep, gpointer data);
+
+/* The setup method, this will be called when the plugin is
+ * initialized. In the future it may also be called when the plugin
+ * is disabled. */
+typedef gint (*EPluginLibEnableFunc) (EPluginLib *ep, gint enable);
+
+typedef gpointer (*EPluginLibGetConfigureWidgetFunc) (EPluginLib *ep);
+
+/**
+ * struct _EPluginLib -
+ *
+ * @plugin: Superclass.
+ * @location: The filename of the shared object.
+ * @module: The GModule once it is loaded.
+ *
+ * This is a concrete EPlugin class. It loads and invokes dynamically
+ * loaded libraries using GModule. The shared object isn't loaded
+ * until the first callback is invoked.
+ *
+ * When the plugin is loaded, and if it exists, "e_plugin_lib_enable"
+ * will be invoked to initialize the plugin.
+ **/
+struct _EPluginLib {
+ EPlugin parent;
+
+ gchar *location;
+ GModule *module;
+};
+
+struct _EPluginLibClass {
+ EPluginClass parent_class;
+};
+
+GType e_plugin_lib_get_type (void);
+void e_plugin_lib_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_PLUGIN_LIB_H */
diff --git a/modules/plugin-lib/evolution-module-plugin-lib.c b/modules/plugin-lib/evolution-module-plugin-lib.c
new file mode 100644
index 0000000000..833ca5906d
--- /dev/null
+++ b/modules/plugin-lib/evolution-module-plugin-lib.c
@@ -0,0 +1,41 @@
+/*
+ * evolution-module-plugin-lib.c
+ *
+ * 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)
+ *
+ */
+
+#include <config.h>
+
+#include "e-plugin-lib.h"
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ /* Register dynamically loaded types. */
+
+ e_plugin_lib_register_type (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
diff --git a/modules/plugin-mono/Camel.cs b/modules/plugin-mono/Camel.cs
new file mode 100644
index 0000000000..4ad80e7012
--- /dev/null
+++ b/modules/plugin-mono/Camel.cs
@@ -0,0 +1,1278 @@
+
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace Camel {
+ [StructLayout (LayoutKind.Sequential)]
+ public struct CamelException {
+ public int id;
+ public string desc;
+ }
+
+ public class Arg {
+ public enum Tag : uint {
+ END = 0,
+ IGNORE = 1,
+ FIRST = 1024,
+
+ TYPE = 0xf0000000, /* type field for tags */
+ TAG = 0x0fffffff, /* tag field for args */
+
+ OBJ = 0x00000000, /* object */
+ INT = 0x10000000, /* int */
+ DBL = 0x20000000, /* double */
+ STR = 0x30000000, /* c string */
+ PTR = 0x40000000, /* ptr */
+ BOO = 0x50000000 /* bool */
+ }
+ }
+
+ public class Exception : System.ApplicationException {
+ public enum Type {
+ NONE = 0,
+ SYSTEM = 1
+ }
+
+ public Type id;
+ public string desc;
+
+ public Exception(CamelException ex) {
+ id = (Type)ex.id;
+ desc = ex.desc;
+ }
+
+ public Exception(Type _id, string _desc) {
+ id = _id;
+ desc = _desc;
+ }
+ }
+
+ public class Util {
+ [DllImport("camel-1.2")] static extern int camel_init(string certdir, bool nss);
+
+ public static void Init(string certdir, bool nss) {
+ if (camel_init(certdir, nss) != 0)
+ throw new Exception(Exception.Type.SYSTEM, "Init failure");
+ }
+
+ public static string [] getUIDArray(IntPtr o) {
+ GPtrArray pa = (GPtrArray)Marshal.PtrToStructure(o, typeof(GPtrArray));
+ string [] uids = new string[pa.len];
+
+ for (int i=0;i<pa.len;i++) {
+ IntPtr x = Marshal.ReadIntPtr(pa.pdata, i * Marshal.SizeOf(typeof(IntPtr)));
+ uids[i] = Marshal.PtrToStringAuto(x);
+ }
+
+ return uids;
+ }
+/*
+ public static IntPtr setUIDs(string [] uids) {
+
+ }
+*/
+ public struct UIDArray {
+ public string [] uids;
+ public int len;
+
+ public UIDArray(string [] _uids) {
+ uids = _uids;
+ len = _uids.Length;
+ }
+
+ public UIDArray(IntPtr raw) {
+ uids = new string[0];
+ len = 0;
+ Marshal.PtrToStructure(raw, this);
+ }
+ }
+ }
+
+ public class Object {
+ // should be library scope
+ public IntPtr cobject;
+ private int finaliseID = -1;
+
+ protected EventHandlerList events = new EventHandlerList();
+
+ // reffing & wrapping stuff.
+ struct CamelObject {
+ public IntPtr klass;
+ }
+
+ struct CamelObjectClass {
+ public IntPtr parent;
+ int magic;
+ IntPtr next;
+ IntPtr prev;
+ public string name;
+ };
+
+ private static Hashtable types = new Hashtable();
+ private static Hashtable objects = new Hashtable();
+
+ [DllImport("camel-1.2")] static extern void camel_object_ref(IntPtr raw);
+ [DllImport("camel-1.2")] static extern void camel_object_unref(IntPtr raw);
+
+ public Object(IntPtr raw) {
+ // ok this is a hack around c# crap to do with unargumented constructors.
+ // we can bypass to a null raw so we can properly instantiate new types
+ if (raw != (IntPtr)0) {
+ cobject = raw;
+ toCamel(this);
+ }
+ }
+
+ public Object() {
+ // this is invalid?
+ }
+
+ ~Object() {
+ System.Console.WriteLine("object disposed " + cobject + " type " + this);
+
+ // well we can never get a finalised event anyway ...
+ if (finalise_id != -1)
+ camel_object_remove_event(cobject, finalise_id);
+ if (meta_changed_id != -1)
+ camel_object_remove_event(cobject, meta_changed_id);
+
+ objects.Remove(cobject);
+ camel_object_remove_event(cobject, finaliseID);
+ finaliseID = -1;
+ camel_object_unref(cobject);
+ cobject = (IntPtr)0;
+
+ // FIXME: remove any event hooks too
+ }
+
+ static Object() {
+ types.Add("CamelObject", typeof(Camel.Object));
+ types.Add("CamelSession", typeof(Camel.Session));
+ types.Add("CamelFolder", typeof(Camel.Folder));
+ types.Add("CamelDataWrapper", typeof(Camel.DataWrapper));
+ types.Add("CamelMedium", typeof(Camel.Medium));
+ types.Add("CamelMimeMessage", typeof(Camel.MimeMessage));
+ types.Add("CamelMimePart", typeof(Camel.MimePart));
+ types.Add("CamelMultipart", typeof(Camel.Multipart));
+
+ types.Add("CamelStore", typeof(Camel.Store));
+ types.Add("CamelTransport", typeof(Camel.Transport));
+ types.Add("CamelAddress", typeof(Camel.Address));
+ types.Add("CamelInternetAddress", typeof(Camel.InternetAddress));
+ types.Add("CamelStream", typeof(Camel.Stream));
+ types.Add("CamelStreamMem", typeof(Camel.StreamMem));
+ types.Add("CamelStreamFs", typeof(Camel.StreamFS));
+ }
+
+ public static void objectFinalised(IntPtr o, IntPtr info, IntPtr data) {
+ System.Console.WriteLine("object finalised " + o);
+ objects.Remove(o);
+ }
+
+ public static Object fromCamel(IntPtr raw) {
+ CamelObject o;
+ CamelObjectClass klass;
+ WeakReference weak = (WeakReference)objects[raw];
+
+ System.Console.WriteLine("object from camel " + raw);
+
+ if (weak != null)
+ return (Object)weak.Target;
+
+ o = (CamelObject)Marshal.PtrToStructure(raw, typeof(CamelObject));
+ if ((object)o == null)
+ return null;
+
+ klass = (CamelObjectClass)Marshal.PtrToStructure(o.klass, typeof(CamelObjectClass));
+ while ((object)klass != null) {
+ Console.WriteLine(" checking is " + klass.name);
+ if (types.ContainsKey(klass.name)) {
+ Console.WriteLine(" yep!");
+ camel_object_ref(raw);
+ return (Camel.Object)Activator.CreateInstance((Type)types[klass.name], new object [] { raw });
+ }
+
+ klass = (CamelObjectClass)Marshal.PtrToStructure(klass.parent, typeof(CamelObjectClass));
+ }
+
+ Console.WriteLine(" unknown type?");
+ camel_object_unref(raw);
+ return null;
+ }
+
+ /* this just registers an object created on the cil side */
+ public static void toCamel(Object res) {
+ System.Console.WriteLine("object to camel " + res.cobject);
+
+ objects.Add(res.cobject, new WeakReference(res));
+ res.finaliseID = camel_object_hook_event(res.cobject, "finalize", (CamelEventFunc)objectFinalised, (IntPtr)0);
+ }
+
+ // Camel event Wrapper and helpers
+ public delegate void CamelEventFunc(IntPtr o, IntPtr info, IntPtr data);
+
+ [DllImport("camel-1.2")] public static extern int camel_object_hook_event(IntPtr raw, string name, CamelEventFunc func, IntPtr data);
+ [DllImport("camel-1.2")] public static extern void camel_object_remove_event(IntPtr raw, int id);
+
+ protected void addEvent(String name, ref int hookid, CamelEventFunc hook, Delegate value) {
+ if (hookid == -1)
+ hookid = camel_object_hook_event(cobject, name, hook, (IntPtr)0);
+ events.AddHandler(name, value);
+ }
+
+ protected void removeEvent(String name, ref int hookid, Delegate value) {
+ events.RemoveHandler(name, value);
+ if (events[name] == null) {
+ camel_object_remove_event(cobject, hookid);
+ hookid = -1;
+ }
+ }
+
+ // object events
+ public delegate void FinaliseEvent(Camel.Object o);
+ public delegate void MetaChangedEvent(Camel.Object o, String name);
+
+ // how to remove these, at dispose time?
+ private int finalise_id = -1;
+ private int meta_changed_id = -1;
+
+ private static void finaliseHook(IntPtr co, IntPtr info, IntPtr data) {
+ Object o = fromCamel(co);
+ FinaliseEvent f;
+
+ if (o != null
+ && (f = (FinaliseEvent)o.events["finalize"]) != null)
+ f(o);
+ }
+
+ private static void metaChangedHook(IntPtr co, IntPtr info, IntPtr data) {
+ Object o = fromCamel(co);
+ MetaChangedEvent f;
+
+ if (o != null
+ && (f = (MetaChangedEvent)o.events["finalize"]) != null)
+ f(o, Marshal.PtrToStringAnsi(info));
+ }
+
+ public event FinaliseEvent Finalise {
+ add { addEvent("finalize", ref finalise_id, (CamelEventFunc)finaliseHook, value); }
+ remove { removeEvent("finalize", ref finalise_id, value); }
+ }
+
+ public event MetaChangedEvent MetaChanged {
+ add { addEvent("meta_changed", ref meta_changed_id, (CamelEventFunc)metaChangedHook, value); }
+ remove { removeEvent("meta_changed", ref meta_changed_id, value); }
+ }
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_object_get_ptr(IntPtr raw, ref CamelException ex, int tag);
+ [DllImport("camel-1.2")] static extern void camel_object_free(IntPtr raw, int tag, IntPtr val);
+ [DllImport("camel-1.2")] static extern int camel_object_get_int(IntPtr raw, ref CamelException ex, int tag);
+
+ // maybe we want an indexer class to get properties?
+ // e.g. name = folder.properties[Folder.Tag.NAME]
+ public String getString(int type) {
+ String s;
+ IntPtr o;
+ CamelException ex = new CamelException();
+
+ o = camel_object_get_ptr(cobject, ref ex, type);
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ s = Marshal.PtrToStringAuto(o);
+ camel_object_free(cobject, type, o);
+
+ return s;
+ }
+
+ public Camel.Object getObject(int type) {
+ IntPtr o;
+ Camel.Object co;
+ CamelException ex = new CamelException();
+
+ o = camel_object_get_ptr(cobject, ref ex, type);
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ co = fromCamel(o);
+ camel_object_free(cobject, type, o);
+
+ return co;
+ }
+
+ public int getInt(int type) {
+ int r;
+ CamelException ex = new CamelException();
+
+ r = camel_object_get_int(cobject, ref ex, type);
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ return r;
+ }
+
+ // meta-data
+ [DllImport("camel-1.2")] static extern String camel_object_meta_get(IntPtr raw, string name);
+ [DllImport("camel-1.2")] static extern bool camel_object_meta_set(IntPtr raw, string name, string value);
+
+ public String metaGet(String name) {
+ return camel_object_meta_get(cobject, name);
+ }
+
+ public bool metaSet(String name, String value) {
+ return camel_object_meta_set(cobject, name, value);
+ }
+ }
+
+ public class Provider {
+ public enum Type {
+ STORE = 0,
+ TRANSPORT = 1
+ }
+ }
+
+ public class Session : Object {
+ public Session(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_session_get_service(IntPtr o, string uri, int type, ref CamelException ex);
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_session_get_service_connected(IntPtr o, string uri, int type, ref CamelException ex);
+
+ public Service getService(string uri, Provider.Type type) {
+ IntPtr s;
+ CamelException ex = new CamelException();
+
+ s = camel_session_get_service(cobject, uri, (int)type, ref ex);
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ return (Service)fromCamel(s);
+ }
+ }
+
+ public class Service : Object {
+ public Service(IntPtr raw) : base(raw) { }
+ // wrap service shit
+ }
+
+ public class Store : Service {
+ public Store(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-provider-1.2")]
+ static extern IntPtr camel_store_get_folder(IntPtr o, string name, int flags, ref CamelException ex);
+
+ Folder getFolder(string name, int flags) {
+ IntPtr s;
+ CamelException ex = new CamelException();
+
+ s = camel_store_get_folder(cobject, name, flags, ref ex);
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ return (Folder)fromCamel(s);
+ }
+
+ void createFolder(string name) {
+ }
+ }
+
+ public class Transport : Service {
+ public Transport(IntPtr raw) : base(raw) { }
+
+ // send to (message, from, reciepients);
+ }
+
+ public class Folder : Camel.Object {
+ public Folder(IntPtr raw) : base(raw) { }
+
+ ~Folder() {
+ if (changed_id != -1)
+ camel_object_remove_event(cobject, changed_id);
+ }
+
+ public enum Tag {
+ NAME = (int) (0x1400 + Arg.Tag.STR),
+ FULL_NAME = (int) (0x1401 + Arg.Tag.STR),
+ STORE = (int) (0x1402 + Arg.Tag.OBJ),
+ PERMANENTFLAGS = (int) (0x1403 + Arg.Tag.INT),
+ TOTAL = (int) (0x1404 + Arg.Tag.INT),
+ UNREAD = (int) (0x1405 + Arg.Tag.INT),
+ DELETED = (int) (0x1406 + Arg.Tag.INT),
+ JUNKED = (int) (0x1407 + Arg.Tag.INT),
+ VISIBLE = (int) (0x1408 + Arg.Tag.INT),
+ UID_ARRAY = (int) (0x1409 + Arg.Tag.PTR),
+ INFO_ARRAY = (int) (0x140a + Arg.Tag.PTR), // GPtrArray
+ PROPERTIES = (int) (0x140b + Arg.Tag.PTR), // GSList of properties
+ }
+
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_folder_get_message(IntPtr o, string uid, ref CamelException ex);
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_folder_get_uids(IntPtr o);
+ [DllImport("camel-provider-1.2")] static extern void camel_folder_free_uids(IntPtr o, IntPtr uids);
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_folder_search_by_expression(IntPtr o, string expr, ref CamelException ex);
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_folder_search_by_uids(IntPtr o, string expr, ref Util.UIDArray uids, ref CamelException ex);
+ [DllImport("camel-provider-1.2")] static extern void camel_folder_search_free(IntPtr o, IntPtr uids);
+
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_folder_get_message_info(IntPtr raw, String uid);
+
+ public MimeMessage getMessage(string uid) {
+ CamelException ex = new CamelException();
+ IntPtr o = camel_folder_get_message(cobject, uid, ref ex);
+
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ return (MimeMessage)fromCamel(o);
+ }
+
+ public MessageInfo getMessageInfo(string uid) {
+ IntPtr o = camel_folder_get_message_info(cobject, uid);
+
+ if (o == (IntPtr)0)
+ return null;
+ else
+ return new MessageInfo(o);
+ }
+
+ public string [] getUIDs() {
+ IntPtr o = camel_folder_get_uids(cobject);
+ Util.UIDArray uids = new Util.UIDArray(o);
+
+ camel_folder_free_uids(cobject, o);
+
+ return uids.uids;
+ }
+
+ public string [] search(string expr) {
+ CamelException ex = new CamelException();
+ IntPtr o = camel_folder_search_by_expression(cobject, expr, ref ex);
+ Util.UIDArray uids;
+
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ uids = new Util.UIDArray(o);
+ camel_folder_search_free(cobject, o);
+
+ return uids.uids;
+ }
+
+ public string [] searchUIDs(string expr, string [] sub) {
+ CamelException ex = new CamelException();
+ Util.UIDArray uids = new Util.UIDArray(sub);
+ IntPtr o = camel_folder_search_by_uids(cobject, expr, ref uids, ref ex);
+
+ if (ex.id != 0)
+ throw new Camel.Exception(ex);
+
+ uids = new Util.UIDArray(o);
+ camel_folder_search_free(cobject, o);
+
+ return uids.uids;
+ }
+
+ public String name {
+ get { return getString((int)Folder.Tag.NAME); }
+ }
+
+ public String fullName {
+ get { return getString((int)Folder.Tag.FULL_NAME); }
+ }
+
+ public Camel.Store store {
+ get { return (Camel.Store)getObject((int)Folder.Tag.STORE); }
+ }
+
+ // Folder events
+ public delegate void ChangedEvent(Camel.Folder f);
+
+ private int changed_id = -1;
+
+ private static void changedHook(IntPtr co, IntPtr info, IntPtr data) {
+ Camel.Folder o = (Camel.Folder)fromCamel(co);
+ ChangedEvent f;
+
+ Console.WriteLine("changed hook called for: " + o.cobject);
+
+ if (o != null
+ && (f = (ChangedEvent)o.events["folder_changed"]) != null)
+ f(o);
+ }
+
+ public event ChangedEvent Changed {
+ add { addEvent("folder_changed", ref changed_id, (CamelEventFunc)changedHook, value); }
+ remove { removeEvent("folder_changed", ref changed_id, value); }
+ }
+ }
+
+ public class DataWrapper : Camel.Object {
+ public DataWrapper(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-1.2")] static extern int camel_data_wrapper_write_to_stream(IntPtr o, IntPtr s);
+ [DllImport("camel-1.2")] static extern int camel_data_wrapper_decode_to_stream(IntPtr o, IntPtr s);
+ [DllImport("camel-1.2")] static extern int camel_data_wrapper_construct_from_stream(IntPtr o, IntPtr s);
+ [DllImport("camel-1.2")] static extern IntPtr camel_data_wrapper_get_mime_type_field(IntPtr o);
+
+ public void writeToStream(Camel.Stream stream) {
+ int res;
+
+ res = camel_data_wrapper_write_to_stream(cobject, stream.cobject);
+ if (res == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO Error");
+ }
+
+ public void decodeToStream(Camel.Stream stream) {
+ int res;
+
+ res = camel_data_wrapper_decode_to_stream(cobject, stream.cobject);
+ if (res == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO Error");
+ }
+
+ public void constructFromStream(Camel.Stream stream) {
+ int res;
+
+ res = camel_data_wrapper_construct_from_stream(cobject, stream.cobject);
+ if (res == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO Error");
+ }
+
+ public ContentType mimeType { get { return new ContentType(camel_data_wrapper_get_mime_type_field(cobject)); } }
+ }
+
+ public class Medium : Camel.DataWrapper {
+ public Medium(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_medium_get_content_object(IntPtr o);
+ [DllImport("camel-1.2")] static extern void camel_medium_set_content_object(IntPtr o, IntPtr s);
+
+ public DataWrapper content {
+ get {
+ IntPtr o = camel_medium_get_content_object(cobject);
+
+ if (o != (IntPtr)0)
+ return (DataWrapper)Object.fromCamel(o);
+ else
+ return null;
+ }
+ set {
+ camel_medium_set_content_object(cobject, value.cobject);
+ }
+ }
+ }
+
+ public class Multipart : Camel.DataWrapper {
+ [DllImport("camel-1.2")] static extern IntPtr camel_multipart_new();
+ [DllImport("camel-1.2")] static extern void camel_multipart_add_part(IntPtr o, IntPtr p);
+ [DllImport("camel-1.2")] static extern void camel_multipart_remove_part(IntPtr o, IntPtr p);
+ [DllImport("camel-1.2")] static extern IntPtr camel_multipart_get_part(IntPtr o, int index);
+ [DllImport("camel-1.2")] static extern int camel_multipart_get_number(IntPtr o);
+
+ public Multipart(IntPtr raw) : base(raw) { }
+
+ public void addPart(MimePart part) {
+ camel_multipart_add_part(cobject, part.cobject);
+ }
+
+ public void removePart(MimePart part) {
+ camel_multipart_add_part(cobject, part.cobject);
+ }
+
+ public MimePart getPart(int index) {
+ IntPtr o;
+
+ o = camel_multipart_get_part(cobject, index);
+ if (o != (IntPtr)0)
+ return (MimePart)Object.fromCamel(o);
+ else
+ return null;
+ }
+
+ public int getNumber() {
+ return camel_multipart_get_number(cobject);
+ }
+
+ // FIXME: finish
+ }
+
+ public class MimePart : Camel.Medium {
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_part_new();
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_part_get_description(IntPtr o);
+ [DllImport("camel-1.2")] static extern void camel_mime_part_set_description(IntPtr o, string s);
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_part_get_disposition(IntPtr o);
+ [DllImport("camel-1.2")] static extern void camel_mime_part_set_disposition(IntPtr o, string s);
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_part_get_filename(IntPtr o);
+ [DllImport("camel-1.2")] static extern void camel_mime_part_set_filename(IntPtr o, string s);
+
+ public MimePart(IntPtr raw) : base(raw) { }
+
+ public string description {
+ get { return Marshal.PtrToStringAuto(camel_mime_part_get_description(cobject)); }
+ set { camel_mime_part_set_description(cobject, value); }
+ }
+
+ public string disposition {
+ get { return Marshal.PtrToStringAuto(camel_mime_part_get_disposition(cobject)); }
+ set { camel_mime_part_set_disposition(cobject, value); }
+ }
+
+ public string filename {
+ get { return Marshal.PtrToStringAuto(camel_mime_part_get_filename(cobject)); }
+ set { camel_mime_part_set_filename(cobject, value); }
+ }
+
+ // FIXME: finish
+ }
+
+ public class MimeMessage : Camel.MimePart {
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_message_new();
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_message_get_subject(IntPtr o);
+ [DllImport("camel-1.2")] static extern void camel_mime_message_set_subject(IntPtr o, string s);
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_message_get_from(IntPtr o);
+ [DllImport("camel-1.2")] static extern void camel_mime_message_set_from(IntPtr o, IntPtr s);
+ [DllImport("camel-1.2")] static extern IntPtr camel_mime_message_get_recipients(IntPtr o, string type);
+ [DllImport("camel-1.2")] static extern void camel_mime_message_set_recipients(IntPtr o, string type, IntPtr s);
+
+ public MimeMessage(IntPtr raw) : base(raw) { }
+
+ /* We need to use factories to create new objects otherwise the parent will instantiate an instance
+ of itself instead during the constructor setup */
+ public MimeMessage() : base((IntPtr)0) {
+ cobject = camel_mime_message_new();
+ toCamel(this);
+ }
+
+ public string subject {
+ get { return Marshal.PtrToStringAuto(camel_mime_message_get_subject(cobject)); }
+ set { camel_mime_message_set_subject(cobject, value); }
+ }
+
+ public InternetAddress from {
+ get { return new InternetAddress(camel_mime_message_get_from(cobject)); }
+ set { camel_mime_message_set_from(cobject, value.cobject); }
+ }
+
+ public InternetAddress to {
+ get { return new InternetAddress(camel_mime_message_get_recipients(cobject, "to")); }
+ set { camel_mime_message_set_recipients(cobject, "to", value.cobject); }
+ }
+
+ public InternetAddress cc {
+ get { return new InternetAddress(camel_mime_message_get_recipients(cobject, "cc")); }
+ set { camel_mime_message_set_recipients(cobject, "cc", value.cobject); }
+ }
+
+ public InternetAddress bcc {
+ get { return new InternetAddress(camel_mime_message_get_recipients(cobject, "bcc")); }
+ set { camel_mime_message_set_recipients(cobject, "bcc", value.cobject); }
+ }
+
+ public InternetAddress resentTO {
+ get { return new InternetAddress(camel_mime_message_get_recipients(cobject, "resent-to")); }
+ set { camel_mime_message_set_recipients(cobject, "resent-to", value.cobject); }
+ }
+
+ public InternetAddress resentCC {
+ get { return new InternetAddress(camel_mime_message_get_recipients(cobject, "resent-cc")); }
+ set { camel_mime_message_set_recipients(cobject, "resent-cc", value.cobject); }
+ }
+
+ public InternetAddress resentBCC {
+ get { return new InternetAddress(camel_mime_message_get_recipients(cobject, "resent-bcc")); }
+ set { camel_mime_message_set_recipients(cobject, "resent-bcc", value.cobject); }
+ }
+ }
+
+ // subclass real streams? or real stream interfaces?
+ public class Stream : Camel.Object {
+ public Stream(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-1.2")] static extern int camel_stream_write(IntPtr o, byte [] data, int len);
+ [DllImport("camel-1.2")] static extern int camel_stream_read(IntPtr o, byte [] data, int len);
+ [DllImport("camel-1.2")] static extern int camel_stream_eos(IntPtr o);
+ [DllImport("camel-1.2")] static extern int camel_stream_close(IntPtr o);
+ [DllImport("camel-1.2")] static extern int camel_stream_flush(IntPtr o);
+ [DllImport("camel-1.2")] static extern int camel_stream_reset(IntPtr o);
+
+ public int write(byte [] data, int len) {
+ int ret;
+
+ ret = camel_stream_write(cobject, data, len);
+ if (ret == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO write Error");
+
+ return ret;
+ }
+
+ public int write(string value) {
+ int ret;
+ byte [] data;
+ System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
+
+ data = enc.GetBytes(value);
+ ret = camel_stream_write(cobject, data, data.Length);
+ if (ret == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO write Error");
+
+ return ret;
+ }
+
+
+ public int read(byte [] data, int len) {
+ int ret;
+
+ ret = camel_stream_read(cobject, data, len);
+ if (ret == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO read Error");
+
+ return ret;
+ }
+
+ public void close() {
+ if (camel_stream_close(cobject) == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO close Error");
+ }
+
+ public void reset() {
+ if (camel_stream_reset(cobject) == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO reset Error");
+ }
+
+ public void flush() {
+ if (camel_stream_flush(cobject) == -1)
+ throw new Exception(Exception.Type.SYSTEM, "IO close Error");
+ }
+
+ public bool eos() {
+ return (camel_stream_eos(cobject) != 0);
+ }
+ }
+
+ public class SeekableStream : Camel.Stream {
+ public SeekableStream(IntPtr raw) : base(raw) { }
+ }
+
+ public class StreamFS : Camel.SeekableStream {
+ public enum Flags {
+ O_RDONLY = 00,
+ O_WRONLY = 01,
+ O_RDWR = 02,
+ O_CREAT = 0100,
+ O_EXCL = 0200,
+ O_TRUNC = 01000,
+ O_APPEND = 02000
+ }
+
+ public static int STDIN_FILENO = 0;
+ public static int STDOUT_FILENO = 1;
+ public static int STDERR_FILENO = 2;
+
+ public StreamFS(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_stream_fs_new_with_name(string name, int flags, int mode);
+ [DllImport("camel-1.2")] static extern IntPtr camel_stream_fs_new_with_fd(int fd);
+
+ public StreamFS(string name, Flags flags, int mode) : base((IntPtr)0) {
+ cobject = camel_stream_fs_new_with_name(name, (int)flags, mode);
+ toCamel(this);
+ }
+
+ public StreamFS(int fd) : base((IntPtr)0) {
+ cobject = camel_stream_fs_new_with_fd(fd);
+ toCamel(this);
+ }
+ }
+
+ // this should obviously be extracted at build time
+ [StructLayout (LayoutKind.Explicit)]
+ struct CamelStreamMem {
+ [FieldOffset(44)] public IntPtr buffer;
+ }
+
+ struct GByteArray {
+ public IntPtr data;
+ public int len;
+ }
+
+ struct GPtrArray {
+ public IntPtr pdata;
+ public int len;
+ }
+
+ public class StreamMem : Camel.SeekableStream {
+ public StreamMem(IntPtr raw) : base(raw) { }
+
+ [DllImport("camel-1.2")]
+ static extern IntPtr camel_stream_mem_new();
+
+ /* stupid c# */
+ public StreamMem() : base((IntPtr)0) {
+ cobject = camel_stream_mem_new();
+ toCamel(this);
+ }
+
+ // should probably have some sort of interface for incremental/range gets too
+ public Byte[] getBuffer() {
+ CamelStreamMem mem = (CamelStreamMem)Marshal.PtrToStructure(cobject, typeof(CamelStreamMem));
+ GByteArray ba = (GByteArray)Marshal.PtrToStructure(mem.buffer, typeof(GByteArray));
+ Byte[] res = new Byte[ba.len];
+
+ Marshal.Copy(ba.data, res, 0, ba.len);
+
+ return res;
+ }
+ }
+
+ // should do iterators etc?
+ public class Address : Camel.Object {
+ public Address(IntPtr raw) : base (raw) { }
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_address_new();
+ [DllImport("camel-1.2")] static extern int camel_address_length(IntPtr raw);
+ [DllImport("camel-1.2")] static extern int camel_address_decode(IntPtr raw, string addr);
+ [DllImport("camel-1.2")] static extern string camel_address_encode(IntPtr raw);
+ [DllImport("camel-1.2")] static extern int camel_address_unformat(IntPtr raw, string addr);
+ [DllImport("camel-1.2")] static extern string camel_address_format(IntPtr raw);
+ [DllImport("camel-1.2")] static extern int camel_address_cat(IntPtr raw, IntPtr src);
+ [DllImport("camel-1.2")] static extern int camel_address_copy(IntPtr raw, IntPtr src);
+ [DllImport("camel-1.2")] static extern void camel_address_remove(IntPtr raw, int index);
+
+ public Address() : base((IntPtr)0) {
+ cobject = camel_address_new();
+ toCamel(this);
+ }
+
+ public int length() {
+ return camel_address_length(cobject);
+ }
+
+ public void decode(string addr) {
+ if (camel_address_decode(cobject, addr) == -1)
+ throw new Exception(Exception.Type.SYSTEM, "Invalid address: " + addr);
+ }
+
+ public string encode() {
+ return camel_address_encode(cobject);
+ }
+
+ public void unformat(string addr) {
+ if (camel_address_unformat(cobject, addr) == -1)
+ throw new Exception(Exception.Type.SYSTEM, "Invalid address: " + addr);
+ }
+
+ public string format() {
+ return camel_address_format(cobject);
+ }
+
+ public void cat(Address from) {
+ camel_address_cat(cobject, from.cobject);
+ }
+
+ public void copy(Address from) {
+ camel_address_copy(cobject, from.cobject);
+ }
+ }
+
+ public class InternetAddress : Camel.Address {
+ public InternetAddress(IntPtr raw) : base (raw) { }
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_internet_address_new();
+ [DllImport("camel-1.2")] static extern int camel_internet_address_add(IntPtr raw, string name, string addr);
+ [DllImport("camel-1.2")] static extern bool camel_internet_address_get(IntPtr raw, out string name, out string addr);
+ [DllImport("camel-1.2")] static extern int camel_internet_address_find_name(IntPtr raw, string name, out string addr);
+ [DllImport("camel-1.2")] static extern int camel_internet_address_find_address(IntPtr raw, string addr, out string name);
+ [DllImport("camel-1.2")] static extern string camel_internet_address_encode_address(out int len, string name, string addr);
+ [DllImport("camel-1.2")] static extern string camel_internet_address_format_address(string name, string addr);
+
+ public InternetAddress() : base((IntPtr)0) {
+ cobject = camel_internet_address_new();
+ toCamel(this);
+ }
+
+ public void add(string name, string addr) {
+ camel_internet_address_add(cobject, name, addr);
+ }
+
+ public bool get(out string name, out string addr) {
+ name = null;
+ addr = null;
+ return camel_internet_address_get(cobject, out name, out addr);
+ }
+
+ // this is a weird arsed interface ...
+ public int findName(string name, out string addr) {
+ addr = null;
+ // FIXME: addr is const, need to marshal to local
+ return camel_internet_address_find_name(cobject, name, out addr);
+ }
+
+ public int findAddress(string addr, out string name) {
+ name = null;
+ return camel_internet_address_find_name(cobject, addr, out name);
+ }
+
+ public static string encode(string name, string addr) {
+ int len = 0;
+ // another weird-arsed interface
+ return camel_internet_address_encode_address(out len, name, addr);
+ }
+
+ public static string format(string name, string addr) {
+ return camel_internet_address_format_address(name, addr);
+ }
+ }
+
+ public class ContentType {
+ public IntPtr cobject;
+
+ public ContentType(IntPtr raw) {
+ cobject = raw;
+ }
+
+ [DllImport("camel-1.2")] static extern bool camel_content_type_is(IntPtr raw, string type, string subtype);
+
+ ~ContentType() {
+ }
+
+ public bool isType(string type, string subtype) {
+ return camel_content_type_is(cobject, type, subtype);
+ }
+ }
+
+ public class MessageInfo {
+ public IntPtr cobject;
+ private Tags user_tags;
+ private Flags user_flags;
+
+ private enum Type {
+ SUBJECT,
+ FROM,
+ TO,
+ CC,
+ MLIST,
+
+ FLAGS,
+ SIZE,
+
+ DATE_SENT,
+ DATE_RECEIVED,
+
+ MESSAGE_ID,
+ REFERENCES,
+
+ USER_FLAGS,
+ USER_TAGS,
+
+ LAST,
+ }
+
+ public class Tags {
+ private MessageInfo mi;
+
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_message_info_user_tag(IntPtr mi, String name);
+ [DllImport("camel-provider-1.2")] static extern bool camel_message_info_set_user_tag(IntPtr mi, String name, String value);
+
+ public Tags(MessageInfo raw) {
+ mi = raw;
+ }
+
+ public String this [String tag] {
+ get {
+ return Marshal.PtrToStringAnsi(camel_message_info_user_tag(mi.cobject, tag));
+ }
+ set {
+ camel_message_info_set_user_tag(mi.cobject, tag, value);
+ }
+ }
+ }
+
+ public class Flags {
+ private MessageInfo mi;
+
+ [DllImport("camel-provider-1.2")] static extern bool camel_message_info_user_flag(IntPtr miptr, String name);
+ [DllImport("camel-provider-1.2")] static extern bool camel_message_info_set_user_flag(IntPtr miptr, String name, bool value);
+
+ // note raw is a pointer to a pointer of tags
+ public Flags(MessageInfo raw) {
+ mi = raw;
+ }
+
+ public bool this [String tag] {
+ get {
+ return camel_message_info_user_flag(mi.cobject, tag);
+ }
+ set {
+ camel_message_info_set_user_flag(mi.cobject, tag, value);
+ }
+ }
+ }
+
+ // only used to calculate offsets
+ private struct CamelMessageInfo {
+ IntPtr summary;
+ uint refcount;
+ string uid;
+ };
+
+ public MessageInfo(IntPtr raw) {
+ cobject = raw;
+ }
+
+ [DllImport("camel-provider-1.2")] static extern void camel_folder_free_message_info(IntPtr raw, IntPtr info);
+ [DllImport("camel-provider-1.2")] static extern void camel_message_info_free(IntPtr info);
+
+ ~MessageInfo() {
+ camel_message_info_free(cobject);
+ }
+
+ [DllImport("camel-provider-1.2")] static extern IntPtr camel_message_info_ptr(IntPtr raw, int type);
+ [DllImport("camel-provider-1.2")] static extern uint camel_message_info_uint32(IntPtr raw, int type);
+ [DllImport("camel-provider-1.2")] static extern uint camel_message_info_time(IntPtr raw, int type);
+
+ public String uid { get { return Marshal.PtrToStringAuto(Marshal.ReadIntPtr(cobject, (int)Marshal.OffsetOf(typeof(CamelMessageInfo), "uid"))); } }
+
+ public String subject { get { return Marshal.PtrToStringAnsi(camel_message_info_ptr(cobject, (int)Type.SUBJECT)); } }
+ public String from { get { return Marshal.PtrToStringAnsi(camel_message_info_ptr(cobject, (int)Type.FROM)); } }
+ public String to { get { return Marshal.PtrToStringAnsi(camel_message_info_ptr(cobject, (int)Type.TO)); } }
+ public String cc { get { return Marshal.PtrToStringAnsi(camel_message_info_ptr(cobject, (int)Type.CC)); } }
+ public String mlist { get { return Marshal.PtrToStringAnsi(camel_message_info_ptr(cobject, (int)Type.MLIST)); } }
+
+ public uint flags { get { return camel_message_info_uint32(cobject, (int)Type.FLAGS); } }
+ public uint size { get { return camel_message_info_uint32(cobject, (int)Type.SIZE); } }
+
+ public Tags userTags {
+ get {
+ if (user_tags == null)
+ user_tags = new Tags(this);
+ return user_tags;
+ }
+ }
+
+ public Flags userFlags {
+ get {
+ if (user_flags == null)
+ user_flags = new Flags(this);
+ return user_flags;
+ }
+ }
+ }
+
+ public class URL {
+ public IntPtr cobject;
+ internal Params param_list;
+
+ // we never instantiate this, we just use it to describe the layout
+ internal struct CamelURL {
+ internal IntPtr protocol;
+ internal IntPtr user;
+ internal IntPtr authmech;
+ internal IntPtr passwd;
+ internal IntPtr host;
+ internal int port;
+ internal IntPtr path;
+ internal IntPtr pparams;
+ internal IntPtr query;
+ internal IntPtr fragment;
+ };
+
+ public class Params {
+ private URL parent;
+
+ internal Params(URL _parent) {
+ parent = _parent;
+ }
+
+ public string this[string name] {
+ set { camel_url_set_param(parent.cobject, name, value); }
+ get { return Marshal.PtrToStringAnsi(camel_url_get_param(parent.cobject, name)); }
+ }
+ }
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_url_new_with_base(IntPtr bbase, string url);
+ [DllImport("camel-1.2")] static extern IntPtr camel_url_new(string url, ref CamelException ex);
+ [DllImport("camel-1.2")] static extern string camel_url_to_string(IntPtr url, int flags);
+ [DllImport("camel-1.2")] static extern void camel_url_free(IntPtr url);
+
+ // this is a shit to wrap, needs accessors or other pain
+ [DllImport("camel-1.2")] static extern void camel_url_set_protocol(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_user(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_authmech(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_passwd(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_host(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_port(IntPtr url, int p);
+ [DllImport("camel-1.2")] static extern void camel_url_set_path(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_param(IntPtr url, string s, string v);
+ [DllImport("camel-1.2")] static extern void camel_url_set_query(IntPtr url, string s);
+ [DllImport("camel-1.2")] static extern void camel_url_set_fragment(IntPtr url, string s);
+
+ [DllImport("camel-1.2")] static extern IntPtr camel_url_get_param(IntPtr url, string s);
+
+ [DllImport("camel-1.2")] static extern string camel_url_encode(string url, string escape);
+ // ugh we can't do this, it writes to its result??
+ // -> use StringBuilder
+ [DllImport("camel-1.2")] static extern IntPtr camel_url_decode(ref string url);
+
+ public URL(string uri) {
+ CamelException ex = new CamelException();
+
+ cobject = camel_url_new(uri, ref ex);
+ if (ex.id != 0)
+ throw new Exception(ex);
+ }
+
+ public URL(URL bbase, string uri) {
+ cobject = camel_url_new_with_base(bbase.cobject, uri);
+ }
+
+ ~URL() {
+ camel_url_free(cobject);
+ }
+
+ /* its ugly but it works */
+ private string field(string name) {
+ return Marshal.PtrToStringAuto(Marshal.ReadIntPtr(cobject, (int)Marshal.OffsetOf(typeof(CamelURL), name)));
+ }
+
+ public string protocol {
+ set { camel_url_set_protocol(cobject, value); }
+ get { return field("protocol"); }
+ }
+
+ public string user {
+ set { camel_url_set_user(cobject, value); }
+ get { return field("user"); }
+ }
+
+ public string authmech {
+ set { camel_url_set_authmech(cobject, value); }
+ get { return field("authmech"); }
+ }
+
+ public string passwd {
+ set { camel_url_set_passwd(cobject, value); }
+ get { return field("passwd"); }
+ }
+
+ public string host {
+ set { camel_url_set_host(cobject, value); }
+ get { return field("host"); }
+ }
+
+ public int port {
+ set { camel_url_set_port(cobject, value); }
+ get { return (int)Marshal.ReadIntPtr(cobject, (int)Marshal.OffsetOf(typeof(CamelURL), "port")); }
+ }
+
+ public string path {
+ set { camel_url_set_path(cobject, value); }
+ get { return field("path"); }
+ }
+
+ public string query {
+ set { camel_url_set_query(cobject, value); }
+ get { return field("query"); }
+ }
+
+ public string fragment {
+ set { camel_url_set_fragment(cobject, value); }
+ get { return field("fragment"); }
+ }
+
+ public Params paramlist {
+ get {
+ if (param_list == null)
+ param_list = new Params(this);
+ return param_list;
+ }
+ }
+
+ public override string ToString() {
+ return camel_url_to_string(cobject, 0);
+ }
+
+ public static string encode(string val) {
+ return camel_url_encode(val, null);
+ }
+
+ public static string encode(string val, string escape) {
+ return camel_url_encode(val, escape);
+ }
+ }
+}
+
+namespace Camel.Hash {
+ public class Stream : System.IO.Stream {
+ protected Camel.Stream substream;
+
+ public Stream(Camel.Stream sub) {
+ substream = sub;
+ }
+
+ public override bool CanSeek { get { return false; } }
+ public override bool CanRead { get { return true; } }
+ public override bool CanWrite { get { return true; } }
+ public override long Length {
+ get {
+ throw new System.IO.IOException("Cannot get stream length");
+ }
+ }
+ public override long Position {
+ get {
+ throw new System.IO.IOException("Cannot get stream position");
+ }
+ set {
+ if (value == 0) {
+ substream.reset();
+ } else {
+ throw new System.IO.IOException("Cannot set stream position");
+ }
+ }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count) {
+ // FIXME: how to add the offset to the buffer?
+ return substream.read(buffer, count);
+ }
+
+ public override void Write(byte[] buffer, int offset, int count) {
+ // FIXME: how to add the offset to the buffer?
+ substream.write(buffer, count);
+ }
+
+ public override void Flush() {
+ substream.flush();
+ }
+
+ public override long Seek(long offset, System.IO.SeekOrigin seek) {
+ throw new System.IO.IOException("Seeking not supported");
+ }
+
+ public override void SetLength(long len) {
+ throw new System.IO.IOException("Cannot set stream length");
+ }
+ }
+}
+
+/*
+namespace Evolution.Mail {
+ class Component : GLib.Object {
+ public Component(IntPtr raw) : base(raw) {}
+ public Component() : base() {}
+
+ ~Component() {
+ Dispose();
+ }
+
+ [DllImport("libevolution-mail.so")] static extern IntPtr mail_component_peek();
+ [DllImport("libevolution-mail.so")] static extern IntPtr mail_component_peek_base_directory(IntPtr component);
+ [DllImport("libevolution-mail.so")] static extern IntPtr mail_component_peek();
+
+ public static Component peek() {
+ return new Component(mail_component_peek());
+ }
+
+ public String baseDirectory {
+ get {}
+ }
+}
+*/
diff --git a/modules/plugin-mono/Evolution.cs b/modules/plugin-mono/Evolution.cs
new file mode 100644
index 0000000000..0db54405b3
--- /dev/null
+++ b/modules/plugin-mono/Evolution.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection;
+
+using Camel;
+
+namespace Evolution {
+ [StructLayout (LayoutKind.Sequential)]
+ public class PopupTarget {
+ public IntPtr popup;
+ public IntPtr widget;
+ public int type;
+ public int mask;
+ };
+
+ [StructLayout (LayoutKind.Sequential)]
+ public class MenuTarget {
+ public IntPtr menu;
+ public IntPtr widget;
+ public int type;
+ public int mask;
+ };
+
+ [StructLayout (LayoutKind.Sequential)]
+ public class EventTarget {
+ public IntPtr aevent;
+ public int type;
+ public int mask;
+ };
+};
+
+namespace Evolution {
+ public class Error {
+ // can we marshal varags from c#?
+ [DllImport("eutil")] static extern int e_error_run(IntPtr parent, string tag, IntPtr end);
+ [DllImport("eutil")] static extern int e_error_run(IntPtr parent, string tag, string arg0, IntPtr end);
+ [DllImport("eutil")] static extern int e_error_run(IntPtr parent, string tag, string arg0, string arg1, IntPtr end);
+ [DllImport("eutil")] static extern int e_error_run(IntPtr parent, string tag, string arg0, string arg1, string arg2, IntPtr end);
+
+ public static int run(IntPtr parent, string tag) {
+ return e_error_run(parent, tag, (IntPtr)0);
+ }
+ public static int run(IntPtr parent, string tag, string arg0) {
+ return e_error_run(parent, tag, arg0, (IntPtr)0);
+ }
+ public static int run(IntPtr parent, string tag, string arg0, string arg1) {
+ return e_error_run(parent, tag, arg0, arg1, (IntPtr)0);
+ }
+ public static int run(IntPtr parent, string tag, string arg0, string arg1, string arg2) {
+ return e_error_run(parent, tag, arg0, arg1, arg2, (IntPtr)0);
+ }
+ }
+}
+
+namespace Evolution.Mail {
+ /* ********************************************************************** */
+ [StructLayout (LayoutKind.Sequential)]
+ public class PopupTargetSelect : PopupTarget {
+ public IntPtr _folder;
+ public string uri;
+ public IntPtr _uids;
+
+ public static PopupTargetSelect get(IntPtr o) {
+ return (PopupTargetSelect)Marshal.PtrToStructure(o, typeof(PopupTargetSelect));
+ }
+
+ public Camel.Folder folder {
+ get { return (Camel.Folder)Camel.Object.fromCamel(_folder); }
+ }
+
+ public string [] uids {
+ get { return Camel.Util.getUIDArray(_uids); }
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public class PopupTargetURI : Evolution.PopupTarget {
+ public string uri;
+
+ public static PopupTargetURI get(IntPtr o) {
+ return (PopupTargetURI)Marshal.PtrToStructure(o, typeof(PopupTargetURI));
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public class PopupTargetPart : PopupTarget {
+ public string mimeType;
+ public IntPtr _part;
+
+ public static PopupTargetPart get(IntPtr o) {
+ return (PopupTargetPart)Marshal.PtrToStructure(o, typeof(PopupTargetPart));
+ }
+
+ public Camel.Object part {
+ get { return (Camel.Object)Camel.Object.fromCamel(_part); }
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct PopupTargetFolder {
+ public Evolution.PopupTarget target;
+ public string uri;
+
+ public static PopupTargetFolder get(IntPtr o) {
+ return (PopupTargetFolder)Marshal.PtrToStructure(o, typeof(PopupTargetFolder));
+ }
+ }
+
+ /* ********************************************************************** */
+ [StructLayout (LayoutKind.Sequential)]
+ public class MenuTargetSelect : MenuTarget {
+ public IntPtr _folder;
+ public string uri;
+ public IntPtr _uids;
+
+ public static MenuTargetSelect get(IntPtr o) {
+ return (MenuTargetSelect)Marshal.PtrToStructure(o, typeof(MenuTargetSelect));
+ }
+
+ public Camel.Folder folder {
+ get { return (Camel.Folder)Camel.Object.fromCamel(_folder); }
+ }
+
+ public string [] uids {
+ get { return Camel.Util.getUIDArray(_uids); }
+ }
+ }
+
+ /* ********************************************************************** */
+ [StructLayout (LayoutKind.Sequential)]
+ public class EventTargetFolder : EventTarget {
+ public string uri;
+
+ public static EventTargetFolder get(IntPtr o) {
+ return (EventTargetFolder)Marshal.PtrToStructure(o, typeof(EventTargetFolder));
+ }
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public class EventTargetMessage : EventTarget {
+ public IntPtr _folder;
+ public string uid;
+ public IntPtr _message;
+
+ public static EventTargetMessage get(IntPtr o) {
+ return (EventTargetMessage)Marshal.PtrToStructure(o, typeof(EventTargetMessage));
+ }
+
+ public Camel.Folder folder {
+ get { return (Camel.Folder)Camel.Object.fromCamel(_folder); }
+ }
+
+ public Camel.MimeMessage message {
+ get { return (Camel.MimeMessage)Camel.Object.fromCamel(_message); }
+ }
+
+ }
+};
diff --git a/modules/plugin-mono/Makefile.am b/modules/plugin-mono/Makefile.am
new file mode 100644
index 0000000000..f4f436ae66
--- /dev/null
+++ b/modules/plugin-mono/Makefile.am
@@ -0,0 +1,22 @@
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"evolution-plugin-mono\" \
+ -I$(top_srcdir) \
+ $(E_UTIL_CFLAGS) \
+ $(MONO_CFLAGS)
+
+module_LTLIBRARIES = libevolution-module-plugin-mono.la
+
+libevolution_module_plugin_mono_la_SOURCES = \
+ evolution-module-plugin-mono.c \
+ e-plugin-mono.c \
+ e-plugin-mono.h
+
+libevolution_module_plugin_mono_la_LIBADD = \
+ $(top_builddir)/e-util/libeutil.la \
+ $(E_UTIL_LIBS) \
+ $(MONO_LIBS)
+
+libevolution_module_plugin_mono_la_LDFLAGS = \
+ -module -avoid-version $(NO_UNDEFINED)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/plugin-mono/e-plugin-mono.c b/modules/plugin-mono/e-plugin-mono.c
new file mode 100644
index 0000000000..1c43fb9d56
--- /dev/null
+++ b/modules/plugin-mono/e-plugin-mono.c
@@ -0,0 +1,261 @@
+/*
+ * e-plugin-mono.c
+ *
+ * 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)
+ *
+ */
+
+#include "e-plugin-mono.h"
+
+#include <sys/types.h>
+#include <string.h>
+
+#include "e-plugin-mono.h"
+
+#include <mono/metadata/debug-helpers.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/threads.h>
+#include <mono/metadata/mono-config.h>
+#include <mono/jit/jit.h>
+
+#define E_PLUGIN_MONO_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_PLUGIN_MONO, EPluginMonoPrivate))
+
+struct _EPluginMonoPrivate {
+ MonoAssembly *assembly;
+ MonoClass *class;
+ MonoObject *plugin;
+ GHashTable *methods;
+};
+
+static MonoDomain *domain;
+static gpointer parent_class;
+static GType plugin_mono_type;
+
+static gchar *
+get_xml_prop (xmlNodePtr node, const gchar *id)
+{
+ xmlChar *prop;
+ gchar *out = NULL;
+
+ prop = xmlGetProp (node, (xmlChar *) id);
+
+ if (prop != NULL) {
+ out = g_strdup ((gchar *) prop);
+ xmlFree (prop);
+ }
+
+ return out;
+}
+
+static void
+plugin_mono_finalize (GObject *object)
+{
+ EPluginMono *plugin_mono;
+
+ plugin_mono = E_PLUGIN_MONO (object);
+
+ g_free (plugin_mono->location);
+ g_free (plugin_mono->handler);
+
+ g_hash_table_destroy (plugin_mono->priv->methods);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint
+plugin_mono_construct (EPlugin *plugin, xmlNodePtr root)
+{
+ EPluginMono *plugin_mono;
+
+ /* Chain up to parent's construct() method. */
+ if (E_PLUGIN_CLASS (parent_class)->construct (plugin, root) == -1)
+ return -1;
+
+ plugin_mono = E_PLUGIN_MONO (plugin);
+ plugin_mono->location = get_xml_prop (root, "location");
+ plugin_mono->handler = get_xml_prop (root, "handler");
+
+ return (plugin_mono->location != NULL) ? 0 : -1;
+}
+
+/*
+ Two approaches:
+ You can have a Evolution.Plugin implementation which has every
+ callback as methods on it. Or you can just use static methods
+ for everything.
+
+ All methods take a single (structured) argument.
+*/
+
+static gpointer
+plugin_mono_invoke (EPlugin *plugin,
+ const gchar *name,
+ gpointer data)
+{
+ EPluginMono *plugin_mono;
+ EPluginMonoPrivate *priv;
+ MonoMethodDesc *d;
+ MonoMethod *m;
+ MonoObject *x = NULL, *res;
+ gpointer *params;
+
+ plugin_mono = E_PLUGIN_MONO (plugin);
+ priv = plugin_mono->priv;
+
+ /* we need to do this every time since we may be called from any thread for some uses */
+ mono_thread_attach (domain);
+
+ if (priv->assembly == NULL) {
+ priv->assembly = mono_domain_assembly_open (
+ domain, plugin_mono->location);
+ if (priv->assembly == NULL) {
+ g_warning (
+ "Can't load assembly '%s'",
+ plugin_mono->location);
+ return NULL;
+ }
+
+ if (plugin_mono->handler == NULL
+ || (priv->class = mono_class_from_name (mono_assembly_get_image (priv->assembly), "", plugin_mono->handler)) == NULL) {
+ } else {
+ priv->plugin = mono_object_new (domain, priv->class);
+ /* could conceivably init with some context too */
+ mono_runtime_object_init (priv->plugin);
+ }
+ }
+
+ m = g_hash_table_lookup (priv->methods, name);
+ if (m == NULL) {
+ if (priv->class) {
+ /* class method */
+ MonoMethod* mono_method;
+ gpointer iter = NULL;
+
+ d = mono_method_desc_new (name, FALSE);
+ /*if (d == NULL) {
+ g_warning ("Can't create method descriptor for '%s'", name);
+ return NULL;
+ }*/
+
+ while ((mono_method = mono_class_get_methods (priv->class, &iter))) {
+ g_print ("\n\a Method name is : <%s>\n\a", mono_method_get_name (mono_method));
+ }
+//mono_class_get_method_from_name
+ m = mono_class_get_method_from_name (priv->class, name, -1);
+ if (m == NULL) {
+ g_warning ("Can't find method callback '%s'", name);
+ return NULL;
+ }
+ } else {
+ /* static method */
+ d = mono_method_desc_new (name, FALSE);
+ if (d == NULL) {
+ g_warning ("Can't create method descriptor for '%s'", name);
+ return NULL;
+ }
+
+ m = mono_method_desc_search_in_image (d, mono_assembly_get_image (priv->assembly));
+ if (m == NULL) {
+ g_warning ("Can't find method callback '%s'", name);
+ return NULL;
+ }
+ }
+
+ g_hash_table_insert (priv->methods, g_strdup (name), m);
+ }
+
+ params = g_malloc0(sizeof (*params)*1);
+ params[0] = &data;
+ res = mono_runtime_invoke (m, priv->plugin, params, &x);
+ /* do i need to free params?? */
+
+ if (x)
+ mono_print_unhandled_exception (x);
+
+ if (res) {
+ gpointer *p = mono_object_unbox (res);
+ return *p;
+ } else
+ return NULL;
+}
+
+static void
+plugin_mono_class_init (EPluginMonoClass *class)
+{
+ GObjectClass *object_class;
+ EPluginClass *plugin_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EPluginMonoPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = plugin_mono_finalize;
+
+ plugin_class = E_PLUGIN_CLASS (class);
+ plugin_class->construct = plugin_mono_construct;
+ plugin_class->invoke = plugin_mono_invoke;
+ plugin_class->type = "mono";
+}
+
+static void
+plugin_mono_init (EPluginMono *plugin_mono)
+{
+ GHashTable *methods;
+
+ methods = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) NULL);
+
+ plugin_mono->priv = E_PLUGIN_MONO_GET_PRIVATE (plugin_mono);
+ plugin_mono->priv->methods = methods;
+}
+
+GType
+e_plugin_mono_get_type (void)
+{
+ return plugin_mono_type;
+}
+
+void
+e_plugin_mono_register_type (GTypeModule *type_module)
+{
+ static const GTypeInfo type_info = {
+ sizeof (EPluginMonoClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) plugin_mono_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPluginMono),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) plugin_mono_init,
+ NULL /* value_table */
+ };
+
+ plugin_mono_type = g_type_module_register_type (
+ type_module, E_TYPE_PLUGIN,
+ "EPluginMono", &type_info, 0);
+
+ domain = mono_jit_init ("Evolution");
+ mono_thread_attach (domain);
+}
diff --git a/modules/plugin-mono/e-plugin-mono.h b/modules/plugin-mono/e-plugin-mono.h
new file mode 100644
index 0000000000..a4ed2d42ec
--- /dev/null
+++ b/modules/plugin-mono/e-plugin-mono.h
@@ -0,0 +1,69 @@
+/*
+ * e-plugin-mono.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_PLUGIN_MONO_H
+#define E_PLUGIN_MONO_H
+
+#include <e-util/e-plugin.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PLUGIN_MONO \
+ (e_plugin_mono_get_type ())
+#define E_PLUGIN_MONO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_PLUGIN_MONO, EPluginMono))
+#define E_PLUGIN_MONO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_PLUGIN_MONO, EPluginMonoClass))
+#define E_IS_PLUGIN_MONO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_PLUGIN_MONO))
+#define E_IS_PLUGIN_MONO_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_PLUGIN_MONO))
+#define E_PLUGIN_MONO_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_PLUGIN_MONO, EPluginMonoClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPluginMono EPluginMono;
+typedef struct _EPluginMonoClass EPluginMonoClass;
+typedef struct _EPluginMonoPrivate EPluginMonoPrivate;
+
+struct _EPluginMono {
+ EPlugin parent;
+ EPluginMonoPrivate *priv;
+
+ gchar *location;
+ gchar *handler;
+};
+
+struct _EPluginMonoClass {
+ EPluginClass parent_class;
+};
+
+GType e_plugin_mono_get_type (void);
+void e_plugin_mono_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_PLUGIN_MONO_H */
diff --git a/modules/plugin-mono/evolution-module-plugin-mono.c b/modules/plugin-mono/evolution-module-plugin-mono.c
new file mode 100644
index 0000000000..75ad534a47
--- /dev/null
+++ b/modules/plugin-mono/evolution-module-plugin-mono.c
@@ -0,0 +1,41 @@
+/*
+ * evolution-module-plugin-mono.c
+ *
+ * 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)
+ *
+ */
+
+#include <config.h>
+
+#include "e-plugin-mono.h"
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ /* Register dynamically loaded types. */
+
+ e_plugin_mono_register_type (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
diff --git a/modules/plugin-python/Makefile.am b/modules/plugin-python/Makefile.am
new file mode 100644
index 0000000000..e6a32c3c83
--- /dev/null
+++ b/modules/plugin-python/Makefile.am
@@ -0,0 +1,31 @@
+AM_CPPFLAGS = \
+ -DG_LOG_DOMAIN=\"evolution-plugin-python\" \
+ -I$(top_srcdir) \
+ $(E_UTIL_CFLAGS) \
+ $(PY_INCLUDES)
+
+module_LTLIBRARIES = libevolution-module-plugin-python.la
+
+libevolution_module_plugin_python_la_SOURCES = \
+ evolution-module-plugin-python.c \
+ e-plugin-python.c \
+ e-plugin-python.h
+
+libevolution_module_plugin_python_la_LIBADD = \
+ -lpthread -ldl -lutil -lm \
+ $(top_builddir)/e-util/libeutil.la \
+ $(E_UTIL_LIBS) \
+ $(PY_LIBS)
+
+libevolution_module_plugin_python_la_LDFLAGS = \
+ -module -avoid-version $(NO_UNDEFINED)
+
+example_sources = \
+ example/hello_python.py \
+ example/org-gnome-hello-python-ui.xml \
+ example/org-gnome-hello-python.eplug.xml \
+ example/Makefile.am
+
+EXTRA_DIST = $(example_sources)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/plugin-python/e-plugin-python.c b/modules/plugin-python/e-plugin-python.c
new file mode 100644
index 0000000000..747ba57bac
--- /dev/null
+++ b/modules/plugin-python/e-plugin-python.c
@@ -0,0 +1,230 @@
+/*
+ * e-plugin-python.c
+ *
+ * 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)
+ *
+ */
+
+/* Include <Python.h> first to avoid:
+ * warning: "_POSIX_C_SOURCE" redefined */
+#include <Python.h>
+
+#include "e-plugin-python.h"
+
+#include <sys/types.h>
+#include <string.h>
+
+#define E_PLUGIN_PYTHON_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_PLUGIN_PYTHON, EPluginPythonPrivate))
+
+struct _EPluginPythonPrivate {
+ PyObject *pModule;
+ PyObject *pClass;
+ PyObject *pFunc;
+ PyObject *pDict;
+ GHashTable *methods;
+};
+
+static gpointer parent_class;
+static GType plugin_python_type;
+
+static gchar *
+get_xml_prop (xmlNodePtr node, const gchar *id)
+{
+ xmlChar *prop;
+ gchar *out = NULL;
+
+ prop = xmlGetProp (node, (xmlChar *) id);
+
+ if (prop != NULL) {
+ out = g_strdup ((gchar *) prop);
+ xmlFree (prop);
+ }
+
+ return out;
+}
+
+static void
+plugin_python_finalize (GObject *object)
+{
+ EPluginPython *plugin_python;
+
+ plugin_python = E_PLUGIN_PYTHON (object);
+
+ g_free (plugin_python->location);
+ g_free (plugin_python->module_name);
+ g_free (plugin_python->pClass);
+
+ g_hash_table_destroy (plugin_python->priv->methods);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint
+plugin_python_construct (EPlugin *plugin, xmlNodePtr root)
+{
+ EPluginPython *plugin_python;
+
+ /* Chain up to parent's construct() method. */
+ if (E_PLUGIN_CLASS (parent_class)->construct (plugin, root) == -1)
+ return -1;
+
+ plugin_python = E_PLUGIN_PYTHON (plugin);
+ plugin_python->location = get_xml_prop (root, "location");
+ plugin_python->module_name = get_xml_prop (root, "module_name");
+ plugin_python->pClass = get_xml_prop (root, "pClass");
+
+ return (plugin_python->location != NULL) ? 0 : -1;
+}
+
+static gpointer
+plugin_python_invoke (EPlugin *plugin,
+ const gchar *name,
+ gpointer data)
+{
+ EPluginPython *plugin_python;
+ EPluginPythonPrivate *priv;
+ PyObject *pModuleName, *pFunc;
+ PyObject *pInstance, *pValue = NULL;
+
+ plugin_python = E_PLUGIN_PYTHON (plugin);
+ priv = plugin_python->priv;
+
+ /* We need to do this every time since we may be called
+ * from any thread for some uses. */
+ Py_Initialize ();
+
+ if (priv->pModule == NULL) {
+ gchar *string;
+
+ pModuleName = PyString_FromString (plugin_python->module_name);
+
+ string = g_strdup_printf (
+ "import sys; "
+ "sys.path.insert(0, '%s')",
+ plugin_python->location);
+ PyRun_SimpleString (string);
+ g_free (string);
+
+ priv->pModule = PyImport_Import (pModuleName);
+
+ Py_DECREF (pModuleName); //Free
+
+ if (priv->pModule == NULL) {
+ PyErr_Print ();
+ g_warning (
+ "Can't load python module '%s'",
+ plugin_python->location);
+ return NULL;
+ }
+
+ priv->pDict = PyModule_GetDict (priv->pModule);
+
+ if (plugin_python->pClass != NULL) {
+ priv->pClass = PyDict_GetItemString (
+ priv->pDict, plugin_python->pClass);
+ }
+ }
+
+ if (priv->pClass) {
+
+ if (PyCallable_Check (priv->pClass))
+ pInstance = PyObject_CallObject (priv->pClass, NULL);
+
+ pValue = PyObject_CallMethod (pInstance, (gchar *) name, NULL);
+
+ } else {
+
+ pFunc = PyDict_GetItemString (priv->pDict, name);
+
+ if (pFunc && PyCallable_Check (pFunc))
+ pValue = PyObject_CallObject (pFunc, NULL);
+ else
+ PyErr_Print ();
+ }
+
+ if (pValue) {
+ Py_DECREF(pValue);
+ /* Fixme */
+ return NULL;
+ } else
+ return NULL;
+}
+
+static void
+plugin_python_class_init (EPluginPythonClass *class)
+{
+ GObjectClass *object_class;
+ EPluginClass *plugin_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EPluginPythonPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = plugin_python_finalize;
+
+ plugin_class = E_PLUGIN_CLASS (class);
+ plugin_class->construct = plugin_python_construct;
+ plugin_class->invoke = plugin_python_invoke;
+ plugin_class->type = "python";
+}
+
+static void
+plugin_python_init (EPluginPython *plugin_python)
+{
+ GHashTable *methods;
+
+ methods = g_hash_table_new_full (
+ g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) NULL);
+
+ plugin_python->priv = E_PLUGIN_PYTHON_GET_PRIVATE (plugin_python);
+ plugin_python->priv->methods = methods;
+}
+
+GType
+e_plugin_python_get_type (void)
+{
+ return plugin_python_type;
+}
+
+void
+e_plugin_python_register_type (GTypeModule *type_module)
+{
+ static const GTypeInfo type_info = {
+ sizeof (EPluginPythonClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) plugin_python_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EPluginPython),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) plugin_python_init,
+ NULL /* value_table */
+ };
+
+ plugin_python_type = g_type_module_register_type (
+ type_module, E_TYPE_PLUGIN,
+ "EPluginPython", &type_info, 0);
+
+ /* TODO Does this mean I can cache the instance of pyobjects? */
+ Py_Initialize ();
+}
diff --git a/modules/plugin-python/e-plugin-python.h b/modules/plugin-python/e-plugin-python.h
new file mode 100644
index 0000000000..9ee780c76c
--- /dev/null
+++ b/modules/plugin-python/e-plugin-python.h
@@ -0,0 +1,70 @@
+/*
+ * e-plugin-python.h
+ *
+ * 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)
+ *
+ */
+
+#ifndef E_PLUGIN_PYTHON_H
+#define E_PLUGIN_PYTHON_H
+
+#include <e-util/e-plugin.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PLUGIN_PYTHON \
+ (e_plugin_python_get_type ())
+#define E_PLUGIN_PYTHON(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_PLUGIN_PYTHON, EPluginPython))
+#define E_PLUGIN_PYTHON_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_PLUGIN_PYTHON, EPluginPythonClass))
+#define E_IS_PLUGIN_PYTHON(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_PLUGIN_PYTHON))
+#define E_IS_PLUGIN_PYTHON_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_PLUGIN_PYTHON))
+#define E_PLUGIN_PYTHON_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_PLUGIN_PYTHON, EPluginPythonClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPluginPython EPluginPython;
+typedef struct _EPluginPythonClass EPluginPythonClass;
+typedef struct _EPluginPythonPrivate EPluginPythonPrivate;
+
+struct _EPluginPython {
+ EPlugin parent;
+ EPluginPythonPrivate *priv;
+
+ gchar *location;
+ gchar *pClass;
+ gchar *module_name;
+};
+
+struct _EPluginPythonClass {
+ EPluginClass parent_class;
+};
+
+GType e_plugin_python_get_type (void);
+void e_plugin_python_register_type (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_PLUGIN_PYTHON_H */
diff --git a/modules/plugin-python/evolution-module-plugin-python.c b/modules/plugin-python/evolution-module-plugin-python.c
new file mode 100644
index 0000000000..84ab3b3e8c
--- /dev/null
+++ b/modules/plugin-python/evolution-module-plugin-python.c
@@ -0,0 +1,41 @@
+/*
+ * evolution-module-plugin-python.c
+ *
+ * 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)
+ *
+ */
+
+#include <config.h>
+
+#include "e-plugin-python.h"
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+ /* Register dynamically loaded types. */
+
+ e_plugin_python_register_type (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
diff --git a/modules/plugin-python/example/Makefile.am b/modules/plugin-python/example/Makefile.am
new file mode 100644
index 0000000000..cc14dc94d9
--- /dev/null
+++ b/modules/plugin-python/example/Makefile.am
@@ -0,0 +1,29 @@
+AM_CPPFLAGS = \
+ -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \
+ -DEVOLUTION_IMAGESDIR=\""$(imagesdir)"\"
+
+@EVO_PLUGIN_RULE@
+
+plugin_DATA = \
+ hello_python.py \
+ org-gnome-hello-python-ui.xml \
+ org-gnome-hello-python.eplug
+
+liborg_gnome_py_plug_test_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED)
+
+errordir = $(privdatadir)/errors
+
+BUILDME = org-gnome-hello-python.eplug \
+$(error_i18n)
+
+BUILT_SOURCES = \
+ $(BUILDME)
+
+EXTRA_DIST = \
+ hello_python.py \
+ org-gnome-hello-python-ui.xml \
+ org-gnome-hello-python.eplug.xml
+
+CLEANFILES = $(BUILT_SOURCES)
+
+-include $(top_srcdir)/git.mk
diff --git a/modules/plugin-python/example/hello_python.py b/modules/plugin-python/example/hello_python.py
new file mode 100644
index 0000000000..16dc2a12f8
--- /dev/null
+++ b/modules/plugin-python/example/hello_python.py
@@ -0,0 +1,5 @@
+'''hello_python.py - Python source designed to '''
+'''demonstrate the use of python Eplugins'''
+
+def say_hello():
+ print 'Hello ! From python'
diff --git a/modules/plugin-python/example/org-gnome-hello-python-ui.xml b/modules/plugin-python/example/org-gnome-hello-python-ui.xml
new file mode 100644
index 0000000000..074960e84d
--- /dev/null
+++ b/modules/plugin-python/example/org-gnome-hello-python-ui.xml
@@ -0,0 +1,16 @@
+<Root>
+ <commands>
+ <cmd name="HelloPy" _label="Hello Python"
+ _tip="Python Plugin Loader tests"
+ />
+ </commands>
+
+ <menu>
+ <placeholder name="MessagePlaceholder">
+ <submenu name="Message">
+ <separator f="" name="sep"/>
+ <menuitem name="HelloPy" verb=""/>
+ </submenu>
+ </placeholder>
+ </menu>
+</Root>
diff --git a/modules/plugin-python/example/org-gnome-hello-python.eplug.xml b/modules/plugin-python/example/org-gnome-hello-python.eplug.xml
new file mode 100644
index 0000000000..8f77d5ba01
--- /dev/null
+++ b/modules/plugin-python/example/org-gnome-hello-python.eplug.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<e-plugin-list>
+ <e-plugin id="org.gnome.evolution.hello_python" type="python" _name="Python Test Plugin" location="@PLUGINDIR@" module_name="hello_python">
+
+ <author name="Johnny Jacob" email="jjohnny@novell.com"/>
+
+ <_description>
+ Test Plugin for Python EPlugin loader.
+ </_description>
+
+ <hook class="org.gnome.evolution.mail.bonobomenu:1.0">
+ <menu id="org.gnome.evolution.mail.browser" target="select">
+ <!-- the path to the bonobo menu description. Any UI items on Evolution should come here -->
+ <ui file="@PLUGINDIR@/org-gnome-hello-python-ui.xml"/>
+ <item type="item" verb="HelloPy" path="/commands/HelloPy" enable="one" activate="say_hello"/>
+ </menu>
+ </hook>
+
+ </e-plugin>
+</e-plugin-list>