[nautilus-sendto] First throw of our new sharing UI



commit 5335cefd3851c08e30485d4a4ae0509bc9254690
Author: Bastien Nocera <hadess hadess net>
Date:   Wed Aug 11 17:45:48 2010 +0100

    First throw of our new sharing UI
    
    The port is powered by libpeas for plugins. See:
    http://live.gnome.org/Nautilus/Future/Sharing
    for background about sharing.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=626553

 configure.in                                       |   42 +-
 src/Makefile.am                                    |   28 +-
 src/extension/Makefile.am                          |   22 +
 src/{ => extension}/nautilus-nste.c                |   53 +-
 src/{ => extension}/nautilus-nste.h                |    0
 src/{ => extension}/nautilus-sendto-module.c       |   16 +-
 src/nautilus-sendto-command.c                      |  694 +++++++-------------
 src/nautilus-sendto-plugin.h                       |  116 ----
 src/nautilus-sendto.ui                             |  495 +++------------
 src/plugins/Makefile.am                            |   41 +-
 src/plugins/evolution/Makefile.am                  |   10 +-
 src/plugins/evolution/evolution.c                  |  319 ++++++----
 src/plugins/evolution/evolution.nst-plugin.in      |    6 +
 src/plugins/nautilus-burn/nautilus-burn.c          |   16 +-
 src/plugins/nautilus-sendto-plugin.c               |  111 ++++
 src/plugins/nautilus-sendto-plugin.h               |  101 +++
 src/plugins/nst-common.c                           |  321 +++++++++
 src/plugins/nst-common.h                           |   31 +-
 src/plugins/removable-devices/Makefile.am          |    7 +-
 src/plugins/removable-devices/removable-devices.c  |  182 +++---
 .../removable-devices.nst-plugin.in                |    6 +
 21 files changed, 1322 insertions(+), 1295 deletions(-)
---
diff --git a/configure.in b/configure.in
index 981a568..d532b1d 100644
--- a/configure.in
+++ b/configure.in
@@ -25,6 +25,7 @@ GNOME_DEBUG_CHECK
 GNOME_COMPILE_WARNINGS([maximum])
 GNOME_CXX_WARNINGS
 GNOME_MAINTAINER_MODE_DEFINES
+GOBJECT_INTROSPECTION_CHECK([0.6.7])
 
 ERROR_CFLAGS="-Wall -Wextra -Werror -Wno_missing_field_initializers -Wno_unused_parameter"
 
@@ -34,10 +35,11 @@ GLIB_REQUIRED=2.25.9
 GTHREAD_REQUIRED=2.6.0
 GTK_REQUIRED=2.90.3
 EBOOK_REQUIRED=1.5.3
-NAUTILUS_EXTENSION=2.31.3
+NAUTILUS_EXTENSION=2.30.1
 DBUS_REQUIRED=1.0
 DBUS_GLIB_REQUIRED=0.60
 GUPNP_REQUIRED=0.13
+LIBPEAS_REQUIRED=0.5.4
 
 AC_SUBST(GLIB_REQUIRED)
 AC_SUBST(GTHREAD_REQUIRED)
@@ -48,14 +50,17 @@ AC_SUBST(BLUETOOTH_REQUIRED)
 AC_SUBST(DBUS_REQUIRED)
 AC_SUBST(GUPNP_REQUIRED)
 
-PKG_CHECK_MODULES(NAUTILUS_SENDTO,\
-	 glib-2.0 >= $GLIB_REQUIRED                \
-	 gthread-2.0 >= $GTHREAD_REQUIRED         \
-	 gmodule-2.0 >= $GLIB_REQUIRED		  \
-	 gtk+-3.0    >= $GTK_REQUIRED)
+PKG_CHECK_MODULES(NAUTILUS_SENDTO,		\
+	 glib-2.0 >= $GLIB_REQUIRED		\
+	 gthread-2.0 >= $GTHREAD_REQUIRED	\
+	 gmodule-2.0 >= $GLIB_REQUIRED		\
+	 gtk+-3.0    >= $GTK_REQUIRED		\
+	 libpeas-1.0 >= $LIBPEAS_REQUIRED)
 AC_SUBST(NAUTILUS_SENDTO_CFLAGS)
 AC_SUBST(NAUTILUS_SENDTO_LIBS)
 
+PKG_CHECK_MODULES(GIO, gio-2.0)
+
 PKG_CHECK_MODULES(NAUTILUS_EXT_SENDTO,\
 	 libnautilus-extension >= $NAUTILUS_EXTENSION)
 AC_SUBST(NAUTILUS_EXT_SENDTO_CFLAGS)
@@ -128,7 +133,7 @@ for plugin in ${used_plugins}; do
 
 	case ${plugin} in
 		evolution)
-			PKG_CHECK_MODULES(NST_EBOOK, libebook-1.2 >= $EBOOK_REQUIRED,
+			PKG_CHECK_MODULES(NST_EBOOK, libebook-1.2 >= $EBOOK_REQUIRED libpeas-1.0,
 					   enable_evolution=yes, enable_evolution=no)
 			if test "${enable_evolution}" != "yes" ; then
 				plugin_error_or_ignore "you need libebook from evolution-data-server to build the Evolution plugin"
@@ -147,7 +152,7 @@ for plugin in ${used_plugins}; do
 
 			GAJIM_SHARE_DIR="$GAJIM_PATH"/share/gajim
 
-			PKG_CHECK_MODULES(DBUS, dbus-1 >= $DBUS_REQUIRED dbus-glib-1 >= $DBUS_GLIB_REQUIRED,
+			PKG_CHECK_MODULES(DBUS, dbus-1 >= $DBUS_REQUIRED dbus-glib-1 >= $DBUS_GLIB_REQUIRED libpeas-1.0,
 					  [
 					   AC_SUBST(DBUS_CFLAGS)
 					   AC_SUBST(DBUS_LIBS)
@@ -164,31 +169,19 @@ for plugin in ${used_plugins}; do
 			fi
 		;;
 		nautilus-burn)
-			PKG_CHECK_MODULES(GIO, gio-2.0,
-					  enable_burn=yes, enable_burn=no)
-			if test "${enable_burn}" != "yes" ; then
-				plugin_error_or_ignore "you need gio installed for the nautilus-burn plugin"
-				add_plugin="0"
-			fi
+		;;
+		removable-devices)
 		;;
 		pidgin)
-			PKG_CHECK_MODULES(PIDGIN, dbus-glib-1 >= $DBUS_GLIB_REQUIRED,
+			PKG_CHECK_MODULES(PIDGIN, dbus-glib-1 >= $DBUS_GLIB_REQUIRED libpeas-1.0,
 					  enable_pidgin=yes, enable_pidgin=no)
 			if test "${enable_pidgin}" != "yes" ; then
 				plugin_error_or_ignore "you need dbus-glib to build the pidgin plugin"
 				add_plugin="0"
 			fi
 		;;
-		removable-devices)
-			PKG_CHECK_MODULES(GIO, gio-2.0,
-					  enable_removable=yes, enable_removable=no)
-			if test "${enable_removable}" != "yes" ; then
-				plugin_error_or_ignore "you need gio-2.0 to build the removable-devices plugin"
-				add_plugin="0"
-			fi
-		;;
 		upnp)
-			PKG_CHECK_MODULES(UPNP, gupnp-1.0 >= $GUPNP_REQUIRED,
+			PKG_CHECK_MODULES(UPNP, gupnp-1.0 >= $GUPNP_REQUIRED libpeas-1.0,
 					  enable_upnp=yes, enable_upnp=no)
 			if test "${enable_upnp}" != "yes" ; then
 				plugin_error_or_ignore "you need gupnp installed for the upnp plugin"
@@ -241,6 +234,7 @@ AM_GLIB_GNU_GETTEXT
 AC_OUTPUT([
 Makefile
 src/Makefile
+src/extension/Makefile
 src/nautilus-sendto.pc
 src/plugins/Makefile
 src/plugins/evolution/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index b1ef4bd..d96a3f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,19 +1,18 @@
-SUBDIRS = plugins
+SUBDIRS = extension plugins
 INCLUDES =					\
 	-DDATADIR=\"$(datadir)\"		\
-	-DPLUGINDIR=\"$(libdir)/nautilus-sendto/plugins\"	\
+	-DPLUGINDIR=\"$(pkglibdir)/plugins\"	\
+	-DLIBDIR=\"$(pkglibdir)\"		\
 	-I$(top_srcdir)				\
 	-I$(top_builddir)			\
-	-DUIDIR=\""$(uidir)"\"		\
+	-I$(top_srcdir)/src/plugins		\
+	-DUIDIR=\""$(uidir)"\"			\
 	-DLOCALEDIR="\"$(datadir)/locale\""	\
 	$(NAUTILUS_SENDTO_CFLAGS)		\
 	$(NAUTILUS_EXT_SENDTO_CFLAGS)		\
 	$(DISABLE_DEPRECATED)			\
 	$(WARN_CFLAGS)
 
-nautilus_sendto_includedir = $(includedir)/nautilus-sendto/
-nautilus_sendto_include_HEADERS = nautilus-sendto-plugin.h
-
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = nautilus-sendto.pc
 
@@ -22,7 +21,6 @@ uidir = $(datadir)/nautilus-sendto/ui
 
 noinst_LTLIBRARIES = libnstplugin.la
 libnstplugin_la_SOURCES =			\
-	nautilus-sendto-plugin.h		\
 	nst-enum-types.c			\
 	nst-enum-types.h
 libnstplugin_la_LIBADD = $(NAUTILUS_SENDTO_LIBS)
@@ -30,19 +28,9 @@ libnstplugin_la_LIBADD = $(NAUTILUS_SENDTO_LIBS)
 bin_PROGRAMS = nautilus-sendto
 
 nautilus_sendto_SOURCES = nautilus-sendto-command.c
-nautilus_sendto_LDADD = $(NAUTILUS_SENDTO_LIBS) libnstplugin.la
-
-nautilus_extensiondir = $(NAUTILUS_EXTENSION_DIR)
-nautilus_extension_LTLIBRARIES = libnautilus-sendto.la
-libnautilus_sendto_la_SOURCES =		\
-	nautilus-nste.c			\
-	nautilus-nste.h			\
-	nautilus-sendto-module.c
-
-libnautilus_sendto_la_LDFLAGS = -module -avoid-version -no-undefined
-libnautilus_sendto_la_LIBADD  = $(NAUTILUS_EXT_SENDTO_LIBS)
+nautilus_sendto_LDADD = $(NAUTILUS_SENDTO_LIBS) libnstplugin.la $(builddir)/plugins/libnautilussendto-1.0.la
 
-nst_headers_to_scan_for_enums = nautilus-sendto-plugin.h
+nst_headers_to_scan_for_enums = plugins/nautilus-sendto-plugin.h
 # Generate the enums source code, with glib-mkenums:
 # This is based on the same Makefile.am stuff in pango:
 nst_built_headers = nst-enum-types.h
@@ -58,7 +46,7 @@ nst-enum-types.h: $(nst_headers_to_scan_for_enums) Makefile
 
 nst-enum-types.c: $(nst_headers_to_scan_for_enums) Makefile nst-enum-types.h
 	$(AM_V_GEN) (cd $(srcdir) && glib-mkenums \
-			--fhead "#include <nautilus-sendto-plugin.h>\n" \
+			--fhead "#include <plugins/nautilus-sendto-plugin.h>\n" \
 			--fhead "#include \"nst-enum-types.h\"\n" \
 			--fhead "#include <glib-object.h>" \
 			--fprod "\n/* enumerations from \"@filename \" */" \
diff --git a/src/extension/Makefile.am b/src/extension/Makefile.am
new file mode 100644
index 0000000..9aaf4b0
--- /dev/null
+++ b/src/extension/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES =					\
+	-DDATADIR=\"$(datadir)\"		\
+	-DPLUGINDIR=\"$(libdir)/nautilus-sendto/plugins\"	\
+	-I$(top_srcdir)				\
+	-I$(top_builddir)			\
+	-DUIDIR=\""$(uidir)"\"		\
+	-DLOCALEDIR="\"$(datadir)/locale\""	\
+	$(NAUTILUS_SENDTO_CFLAGS)		\
+	$(NAUTILUS_EXT_SENDTO_CFLAGS)		\
+	$(DISABLE_DEPRECATED)			\
+	$(WARN_CFLAGS)
+
+nautilus_extensiondir = $(NAUTILUS_EXTENSION_DIR)
+nautilus_extension_LTLIBRARIES = libnautilus-sendto.la
+libnautilus_sendto_la_SOURCES =		\
+	nautilus-nste.c			\
+	nautilus-nste.h			\
+	nautilus-sendto-module.c
+
+libnautilus_sendto_la_LDFLAGS = -module -avoid-version -no-undefined
+libnautilus_sendto_la_LIBADD  = $(NAUTILUS_EXT_SENDTO_LIBS)
+
diff --git a/src/nautilus-nste.c b/src/extension/nautilus-nste.c
similarity index 86%
rename from src/nautilus-nste.c
rename to src/extension/nautilus-nste.c
index acd6c9e..3deac38 100644
--- a/src/nautilus-nste.c
+++ b/src/extension/nautilus-nste.c
@@ -1,6 +1,6 @@
 /*
- *  Nautilus-sendto 
- * 
+ *  Nautilus-sendto
+ *
  *  Copyright (C) 2004 Free Software Foundation, Inc.
  *
  *  This library is free software; you can redistribute it and/or
@@ -17,8 +17,8 @@
  *  License along with this library; if not, write to the Free
  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  Author: Roberto Majadas <roberto majadas openshine com> 
- * 
+ *  Author: Roberto Majadas <roberto majadas openshine com>
+ *
  */
 
 #include <config.h>
@@ -34,7 +34,7 @@ static GObjectClass *parent_class;
 
 static void
 sendto_callback (NautilusMenuItem *item,
-	      gpointer          user_data)
+		 gpointer          user_data)
 {
 	GList            *files, *scan;
 	NautilusFileInfo *file;
@@ -57,7 +57,7 @@ sendto_callback (NautilusMenuItem *item,
 	g_spawn_command_line_async (cmd->str, NULL);
 
 	g_string_free (cmd, TRUE);
-}	 
+}
 
 static GList *
 nautilus_nste_get_file_items (NautilusMenuProvider *provider,
@@ -86,7 +86,7 @@ nautilus_nste_get_file_items (NautilusMenuProvider *provider,
 	}
 
 	one_item = (files != NULL) && (files->next == NULL);
-	if (one_item && 
+	if (one_item &&
 	    !nautilus_file_info_is_directory ((NautilusFileInfo *)files->data)) {
 		item = nautilus_menu_item_new ("NautilusNste::sendto",
 					       _("Send To..."),
@@ -98,51 +98,45 @@ nautilus_nste_get_file_items (NautilusMenuProvider *provider,
 					       _("Send files by mail, instant message..."),
 					       "document-send");
 	}
-  g_signal_connect (item, 
-      "activate",
-      G_CALLBACK (sendto_callback),
-      provider);
-  g_object_set_data_full (G_OBJECT (item), 
-      "files",
-      nautilus_file_info_list_copy (files),
-      (GDestroyNotify) nautilus_file_info_list_free);
+	g_signal_connect (item,
+			  "activate",
+			  G_CALLBACK (sendto_callback),
+			  provider);
+	g_object_set_data_full (G_OBJECT (item),
+				"files",
+				nautilus_file_info_list_copy (files),
+				(GDestroyNotify) nautilus_file_info_list_free);
 
-  items = g_list_append (items, item);
+	items = g_list_append (items, item);
 
 	return items;
 }
 
-
-static void 
+static void
 nautilus_nste_menu_provider_iface_init (NautilusMenuProviderIface *iface)
 {
 	iface->get_file_items = nautilus_nste_get_file_items;
 }
 
-
-static void 
+static void
 nautilus_nste_instance_init (NautilusNste *nste)
 {
 }
 
-
 static void
 nautilus_nste_class_init (NautilusNsteClass *class)
 {
 	parent_class = g_type_class_peek_parent (class);
 }
 
-
 static GType nste_type = 0;
 
-
 GType
-nautilus_nste_get_type (void) 
+nautilus_nste_get_type (void)
 {
 	return nste_type;
 }
 
-
 void
 nautilus_nste_register_type (GTypeModule *module)
 {
@@ -151,7 +145,7 @@ nautilus_nste_register_type (GTypeModule *module)
 		(GBaseInitFunc) NULL,
 		(GBaseFinalizeFunc) NULL,
 		(GClassInitFunc) nautilus_nste_class_init,
-		NULL, 
+		NULL,
 		NULL,
 		sizeof (NautilusNste),
 		0,
@@ -165,12 +159,13 @@ nautilus_nste_register_type (GTypeModule *module)
 	};
 
 	nste_type = g_type_module_register_type (module,
-					         G_TYPE_OBJECT,
-					         "NautilusNste",
-					         &info, 0);
+						 G_TYPE_OBJECT,
+						 "NautilusNste",
+						 &info, 0);
 
 	g_type_module_add_interface (module,
 				     nste_type,
 				     NAUTILUS_TYPE_MENU_PROVIDER,
 				     &menu_provider_iface_info);
 }
+
diff --git a/src/nautilus-nste.h b/src/extension/nautilus-nste.h
similarity index 100%
rename from src/nautilus-nste.h
rename to src/extension/nautilus-nste.h
diff --git a/src/nautilus-sendto-module.c b/src/extension/nautilus-sendto-module.c
similarity index 94%
rename from src/nautilus-sendto-module.c
rename to src/extension/nautilus-sendto-module.c
index b2a407a..75dfa3d 100644
--- a/src/nautilus-sendto-module.c
+++ b/src/extension/nautilus-sendto-module.c
@@ -1,7 +1,7 @@
 /*
- *  Nautilus SendTo 
- * 
- *  Copyright (C) 2005 Roberto Majadas 
+ *  Nautilus SendTo
+ *
+ *  Copyright (C) 2005 Roberto Majadas
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public
@@ -18,7 +18,7 @@
  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  Author: Roberto Majadas <roberto majadas openshine com>
- * 
+ *
  */
 
 #include <config.h>
@@ -37,24 +37,20 @@ nautilus_module_initialize (GTypeModule*module)
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 }
 
-
 void
 nautilus_module_shutdown (void)
 {
 }
 
-
-void 
+void
 nautilus_module_list_types (const GType **types,
 			    int          *num_types)
 {
 	static GType type_list[1];
-	
+
 	type_list[0] = NAUTILUS_TYPE_NSTE;
 	*types = type_list;
 
 	*num_types = 1;
 }
 
-
-
diff --git a/src/nautilus-sendto-command.c b/src/nautilus-sendto-command.c
index 1496411..f78526d 100644
--- a/src/nautilus-sendto-command.c
+++ b/src/nautilus-sendto-command.c
@@ -1,8 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* 
+/*
  * Copyright (C) 2004 Roberto Majadas
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -19,36 +17,41 @@
  * Boston, MA 02110-1301  USA.
  *
  * Author:  Roberto Majadas <roberto majadas openshine com>
+ *          Bastien Nocera <hadess hadess net>
  */
 
 #include "config.h"
 #include <string.h>
 #include <stdlib.h>
+#include <libpeas/peas.h>
+#include <girepository.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <gtk/gtk.h>
 #include "nautilus-sendto-plugin.h"
 
 #define NAUTILUS_SENDTO_LAST_MEDIUM	"last-medium"
-#define NAUTILUS_SENDTO_LAST_COMPRESS	"last-compress"
 #define NAUTILUS_SENDTO_STATUS_LABEL_TIMEOUT_SECONDS 10
 
 #define UNINSTALLED_PLUGINDIR "plugins/removable-devices"
-#define UNINSTALLED_SOURCE "nautilus-sendto-command.c"
-
-#define SOEXT           ("." G_MODULE_SUFFIX)
-#define SOEXT_LEN       (strlen (SOEXT))
 
 enum {
 	COLUMN_ICON,
+	COLUMN_ID,
+	COLUMN_PAGE_NUM,
 	COLUMN_DESCRIPTION,
 	NUM_COLUMNS,
 };
 
 /* Options */
 static char **filenames = NULL;
+static gboolean run_from_build_dir = FALSE;
+
+static PeasEngine *engine;
+static PeasExtensionSet *exten_set;
 
 GList *file_list = NULL;
+char **mime_types = NULL;
 gboolean has_dirs = FALSE;
 GList *plugin_list = NULL;
 GHashTable *hash ;
@@ -60,193 +63,27 @@ typedef struct _NS_ui NS_ui;
 
 struct _NS_ui {
 	GtkWidget *dialog;
-	GtkWidget *options_combobox;
+	GtkWidget *options_treeview;
+	GtkWidget *contacts_notebook;
 	GtkWidget *send_to_label;
 	GtkWidget *hbox_contacts_ws;
 	GtkWidget *cancel_button;
 	GtkWidget *send_button;
-	GtkWidget *pack_combobox;
-	GtkWidget *pack_checkbutton;
-	GtkWidget *pack_entry;
-	GList *contact_widgets;
-
-	GtkWidget *status_box;
-	GtkWidget *status_image;
-	GtkWidget *status_label;
-	guint status_timeoutid;
 };
 
 static const GOptionEntry entries[] = {
-	{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "Files to send", "[FILES...]" },
+	{ "run-from-build-dir", 'b', 0, G_OPTION_ARG_NONE, &run_from_build_dir, N_("Run from build directory"), NULL },
+	{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, N_("Files to send"), "[FILES...]" },
 	{ NULL }
 };
 
-static void 
+static void
 destroy_dialog (GtkWidget *widget, gpointer data )
 {
         gtk_main_quit ();
 }
 
-static char *
-get_filename_from_list (void)
-{
-	GList *l;
-	GString *common_part = NULL;
-	gboolean matches = TRUE;
-	guint offset = 0;
-	const char *encoding;
-	gboolean use_utf8 = TRUE;
-
-	encoding = g_getenv ("G_FILENAME_ENCODING");
-
-	if (encoding != NULL && strcasecmp(encoding, "UTF-8") != 0)
-		use_utf8 = FALSE;
-
-	if (file_list == NULL)
-		return NULL;
-
-	common_part = g_string_new("");
-
-	while (TRUE) {
-		gunichar cur_char = '\0';
-		for (l = file_list; l ; l = l->next) {
-			char *path = NULL, *name = NULL;
-			char *offset_name = NULL;
-
-			path = g_filename_from_uri ((char *) l->data,
-					NULL, NULL);
-			if (!path)
-				break;
-
-			name = g_path_get_basename (path);
-
-			if (!use_utf8) {
-				char *tmp;
-
-				tmp = g_filename_to_utf8 (name, -1,
-						NULL, NULL, NULL);
-				g_free (name);
-				name = tmp;
-			}
-
-			if (!name) {
-				g_free (path);
-				break;
-			}
-
-			if (offset >= g_utf8_strlen (name, -1)) {
-				g_free(name);
-				g_free(path);
-				matches = FALSE;
-				break;
-			}
-
-			offset_name = g_utf8_offset_to_pointer (name, offset);
-
-			if (offset_name == g_utf8_strrchr (name, -1, '.')) {
-				g_free (name);
-				g_free (path);
-				matches = FALSE;
-				break;
-			}
-			if (cur_char == '\0') {
-				cur_char = g_utf8_get_char (offset_name);
-			} else if (cur_char != g_utf8_get_char (offset_name)) {
-				g_free (name);
-				g_free (path);
-				matches = FALSE;
-				break;
-			}
-			g_free (name);
-			g_free (path);
-		}
-		if (matches == TRUE && cur_char != '\0') {
-			offset++;
-			common_part = g_string_append_unichar (common_part,
-					cur_char);
-		} else {
-			break;
-		}
-	}
-
-	if (g_utf8_strlen (common_part->str, -1) < 4) {
-		g_string_free (common_part, TRUE);
-		return NULL;
-	}
-
-	return g_string_free (common_part, FALSE);
-}
-
-static char *
-pack_files (NS_ui *ui)
-{
-	char *file_roller_cmd;
-	const char *filename;
-	GList *l;
-	GString *cmd, *tmp;
-	char *pack_type, *tmp_dir, *tmp_work_dir, *packed_file;
-
-	file_roller_cmd = g_find_program_in_path ("file-roller");
-	filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
-
-	g_assert (filename != NULL && *filename != '\0');
-	
-	tmp_dir = g_strdup_printf ("%s/nautilus-sendto-%s", 
-				   g_get_tmp_dir(), g_get_user_name());	
-	g_mkdir (tmp_dir, 0700);
-	tmp_work_dir = g_strdup_printf ("%s/nautilus-sendto-%s/%li",
-					g_get_tmp_dir(), g_get_user_name(),
-					time(NULL));
-	g_mkdir (tmp_work_dir, 0700);
-	g_free (tmp_dir);
-
-	switch (gtk_combo_box_get_active (GTK_COMBO_BOX(ui->pack_combobox)))
-	{
-	case 0:
-		pack_type = g_strdup (".zip");
-		break;
-	case 1:
-		pack_type = g_strdup (".tar.gz");
-		break;
-	case 2: 
-		pack_type = g_strdup (".tar.bz2");
-		break;
-	default:
-		pack_type = NULL;
-		g_assert_not_reached ();
-	}
-
-	g_settings_set_int (settings,
-			    NAUTILUS_SENDTO_LAST_COMPRESS,
-			    gtk_combo_box_get_active(GTK_COMBO_BOX(ui->pack_combobox)));
-
-	cmd = g_string_new ("");
-	g_string_printf (cmd, "%s --add-to=\"%s/%s%s\"",
-			 file_roller_cmd, tmp_work_dir,
-			 filename,
-			 pack_type);
-
-	/* file-roller doesn't understand URIs */
-	for (l = file_list ; l; l=l->next){
-		char *file;
-
-		file = g_filename_from_uri (l->data, NULL, NULL);
-		g_string_append_printf (cmd," \"%s\"", file);
-		g_free (file);
-	}
-
-	g_spawn_command_line_sync (cmd->str, NULL, NULL, NULL, NULL);
-	g_string_free (cmd, TRUE);
-	tmp = g_string_new("");
-	g_string_printf (tmp,"%s/%s%s", tmp_work_dir,
-			 filename,
-			 pack_type);
-	g_free (tmp_work_dir);
-	packed_file = g_filename_to_uri (tmp->str, NULL, NULL);
-	g_string_free(tmp, TRUE);
-	return packed_file;
-}
-
+#if 0
 static gboolean
 status_label_clear (gpointer data)
 {
@@ -258,10 +95,11 @@ status_label_clear (gpointer data)
 
 	return FALSE;
 }
-
+#endif
 static void
 send_button_cb (GtkWidget *widget, NS_ui *ui)
 {
+#if 0
 	char *f, *error;
 	NstPlugin *p;
 	GtkWidget *w;
@@ -327,8 +165,10 @@ send_button_cb (GtkWidget *widget, NS_ui *ui)
 		file_list = NULL;
 	}
 	destroy_dialog (NULL,NULL);
+#endif
 }
 
+#if 0
 static void
 send_if_no_pack_cb (GtkWidget *widget, NS_ui *ui)
 {
@@ -342,170 +182,133 @@ send_if_no_pack_cb (GtkWidget *widget, NS_ui *ui)
 		send_button_cb (widget, ui);
 	}
 }
+#endif
 
 static void
-toggle_pack_check (GtkWidget *widget, NS_ui *ui)
-{
-	GtkToggleButton *t = GTK_TOGGLE_BUTTON (widget);
-	gboolean enabled, send_enabled;
-
-	enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (t));
-	gtk_widget_set_sensitive (ui->pack_combobox, enabled);
-	gtk_widget_set_sensitive (ui->pack_entry, enabled);
-
-	send_enabled = TRUE;
-
-	if (enabled) {
-		const char *filename;
-
-		filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
-		if (filename == NULL || *filename == '\0')
-			send_enabled = FALSE;
-	}
-
-	gtk_widget_set_sensitive (ui->send_button, send_enabled);
-}
-
-static void
-option_changed (GtkComboBox *cb, NS_ui *ui)
+option_changed (GtkTreeSelection *treeselection,
+		NS_ui *ui)
 {
-	GList *aux;
-	NstPlugin *p;
-	gboolean supports_dirs = FALSE;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	int page_num;
 
-	aux = g_list_nth (ui->contact_widgets, option);
-	option = gtk_combo_box_get_active (GTK_COMBO_BOX(cb));
-	gtk_widget_hide ((GtkWidget *) aux->data);
-	aux = g_list_nth (ui->contact_widgets, option);
-	gtk_widget_show ((GtkWidget *) aux->data);
+	if (gtk_tree_selection_get_selected (treeselection, &model, &iter) == FALSE)
+		return;
 
-	gtk_label_set_mnemonic_widget (GTK_LABEL (ui->send_to_label), aux->data);
+	gtk_tree_model_get (model, &iter,
+			    COLUMN_PAGE_NUM, &page_num,
+			    -1);
 
-	p = (NstPlugin *) g_list_nth_data (plugin_list, option);
-	supports_dirs = (p->info->capabilities & NAUTILUS_CAPS_SEND_DIRECTORIES);
+	gtk_notebook_set_current_page (GTK_NOTEBOOK (ui->contacts_notebook),
+				       page_num);
 
-	if (has_dirs == FALSE || supports_dirs != FALSE) {
-		gboolean toggle;
-
-		toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton));
-		gtk_widget_set_sensitive (ui->pack_combobox, toggle);
-		gtk_widget_set_sensitive (ui->pack_entry, toggle);
-		gtk_widget_set_sensitive (ui->pack_checkbutton, TRUE);
-	} else {
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE);
-		gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE);
-	}
+	/* FIXME: Get a widget in the plugin to grab focus? */
 }
 
 static void
-set_contact_widgets (NS_ui *ui)
-{
-	GList *aux ;
-	GtkWidget *w;
-	NstPlugin *p;
-
-	ui->contact_widgets = NULL;
-
-	for (aux = plugin_list; aux; aux = aux->next){
-		p = (NstPlugin *) aux->data;
-		w = p->info->get_contacts_widget(p);
-		gtk_box_pack_end (GTK_BOX(ui->hbox_contacts_ws),w, TRUE, TRUE, 0);
-		gtk_widget_hide (GTK_WIDGET(w));
-		ui->contact_widgets = g_list_append (ui->contact_widgets, w);
-		if (GTK_IS_ENTRY (w)) {
-			g_signal_connect_after (G_OBJECT (w), "activate",
-						G_CALLBACK (send_if_no_pack_cb), ui);
-		}
-	}
-}
-
-static gboolean
-set_model_for_options_combobox (NS_ui *ui)
+set_model_for_options_treeview (NS_ui *ui)
 {
 	GdkPixbuf *pixbuf;
-        GtkTreeIter iter;
-        GtkListStore *model;
+	GtkTreeIter iter;
+	GtkListStore *model;
 	GtkIconTheme *it;
 	GtkCellRenderer *renderer;
-	GtkWidget *widget;
-	GList *aux;
-	NstPlugin *p;
 	char *last_used = NULL;
 	int i = 0;
-	gboolean last_used_support_dirs = FALSE;
+	GtkTreeViewColumn *column;
+	GtkTreeSelection *selection;
+	GtkTreePath *path;
+	char **list;
+	gboolean supported;
+
+	/* Disable this call if you want to debug */
+	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (ui->contacts_notebook), FALSE);
 
 	it = gtk_icon_theme_get_default ();
 
-	model = gtk_list_store_new (NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
+	model = gtk_list_store_new (NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING);
 
 	last_used = g_settings_get_string (settings,
 					   NAUTILUS_SENDTO_LAST_MEDIUM);
 
-	for (aux = plugin_list; aux; aux = aux->next) {
-		p = (NstPlugin *) aux->data;
-		pixbuf = gtk_icon_theme_load_icon (it, p->info->icon, 16, 
+	/* Populate the tree model */
+	list = peas_engine_get_loaded_plugins (engine);
+	for (i = 0; list[i] != NULL; i++) {
+		GtkWidget *label, *w;
+		PeasPluginInfo *info;
+		PeasExtension *ext;
+		const char *id;
+		int page_num;
+
+		info = peas_engine_get_plugin_info (engine, list[i]);
+		id = peas_plugin_info_get_module_name (info);
+
+		ext = peas_extension_set_get_extension (exten_set, info);
+
+		/* Check if the plugin supports the mime-types of the files we have */
+		if (peas_extension_call (ext, "supports_mime_types", mime_types, &supported) == FALSE ||
+		    supported == FALSE) {
+			g_message ("'%s' does not support mime-types", id);
+			continue;
+		}
+
+		if (peas_extension_call (ext, "get_widget", file_list, &w) == FALSE || w == NULL) {
+			g_warning ("Failed to get widget for %s", id);
+			continue;
+		}
+
+		pixbuf = gtk_icon_theme_load_icon (it, peas_plugin_info_get_icon_name (info), 16,
 						   GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+		label = gtk_label_new (id);
+		page_num = gtk_notebook_append_page (GTK_NOTEBOOK (ui->contacts_notebook), w, label);
+
 		gtk_list_store_append (model, &iter);
 		gtk_list_store_set (model, &iter,
-					COLUMN_ICON, pixbuf,
-					COLUMN_DESCRIPTION, dgettext(p->info->gettext_package, p->info->description),
-					-1);
-		if (last_used != NULL && !strcmp(last_used, p->info->id)) {
+				    COLUMN_ICON, pixbuf,
+				    COLUMN_ID, id,
+				    COLUMN_PAGE_NUM, page_num,
+				    COLUMN_DESCRIPTION, peas_plugin_info_get_name (info),
+				    -1);
+
+		gtk_widget_show (w);
+
+		if (last_used != NULL && !strcmp(last_used, id))
 			option = i;
-			last_used_support_dirs = (p->info->capabilities & NAUTILUS_CAPS_SEND_DIRECTORIES);
-		}
-		i++;
 	}
 	g_free(last_used);
 
-	gtk_combo_box_set_model (GTK_COMBO_BOX(ui->options_combobox),
-				GTK_TREE_MODEL (model));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ui->options_treeview));
+	gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+
+	gtk_tree_view_set_model (GTK_TREE_VIEW (ui->options_treeview),
+				 GTK_TREE_MODEL (model));
+	column = gtk_tree_view_column_new ();
 	renderer = gtk_cell_renderer_pixbuf_new ();
-        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox),
-                                    renderer,
-                                    FALSE);
-        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox), 
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column),
+				    renderer,
+				    FALSE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column),
 					renderer,
-                                        "pixbuf", COLUMN_ICON,
-                                        NULL);		
-        renderer = gtk_cell_renderer_text_new ();
-        g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (ui->options_combobox),
-                                    renderer,
-                                    TRUE);
-        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (ui->options_combobox), 
+					"pixbuf", COLUMN_ICON,
+					NULL);
+	renderer = gtk_cell_renderer_text_new ();
+	g_object_set (G_OBJECT (renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column),
+				    renderer,
+				    TRUE);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column),
 					renderer,
-                                        "text", COLUMN_DESCRIPTION,
-                                        NULL);
+					"text", COLUMN_DESCRIPTION,
+					NULL);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (ui->options_treeview), column);
 
-	g_signal_connect (G_OBJECT (ui->options_combobox), "changed",
+	g_signal_connect (G_OBJECT (selection), "changed",
 			  G_CALLBACK (option_changed), ui);
 
-	gtk_combo_box_set_active (GTK_COMBO_BOX (ui->options_combobox), option);
-
-	/* Grab the focus for the most recently used widget */
-	widget = g_list_nth_data (ui->contact_widgets, option);
-	gtk_widget_grab_focus (widget);
-
-	return last_used_support_dirs;
-}
-
-static void
-pack_entry_changed_cb (GObject *object, GParamSpec *spec, NS_ui *ui)
-{
-	gboolean send_enabled;
-
-	send_enabled = TRUE;
-
-	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton))) {
-		const char *filename;
-
-		filename = gtk_entry_get_text(GTK_ENTRY(ui->pack_entry));
-		if (filename == NULL || *filename == '\0')
-			send_enabled = FALSE;
-	}
-
-	gtk_widget_set_sensitive (ui->send_button, send_enabled);
+	/* Select the previously selected option */
+	path = gtk_tree_path_new_from_indices (option, -1);
+	gtk_tree_selection_select_path (selection, path);
+	gtk_tree_path_free (path);
 }
 
 static void
@@ -528,31 +331,27 @@ nautilus_sendto_create_ui (void)
 	GtkBuilder *app;
 	GError* error = NULL;
 	NS_ui *ui;
-	gboolean one_file = FALSE;
-	gboolean supports_dirs;
 	GtkSettings *gtk_settings;
 	GtkWidget *button_image;
 
 	app = gtk_builder_new ();
-	if (!gtk_builder_add_from_file (app, UIDIR "/" "nautilus-sendto.ui", &error))	{
-		g_warning ("Couldn't load builder file: %s", error->message);
-		g_error_free (error);
+	/* FIXME, use run_from_build_dir instead */
+	if (!gtk_builder_add_from_file (app, "nautilus-sendto.ui", NULL)) {
+		if (!gtk_builder_add_from_file (app, UIDIR "/" "nautilus-sendto.ui", &error)) {
+			g_warning ("Couldn't load builder file: %s", error->message);
+			g_error_free (error);
+		}
 	}
 
 	ui = g_new0 (NS_ui, 1);
 
+	ui->options_treeview = GTK_WIDGET (gtk_builder_get_object (app, "options_treeview"));
+	ui->contacts_notebook = GTK_WIDGET (gtk_builder_get_object (app, "contacts_notebook"));
 	ui->hbox_contacts_ws = GTK_WIDGET (gtk_builder_get_object (app, "hbox_contacts_widgets"));
 	ui->send_to_label = GTK_WIDGET (gtk_builder_get_object (app, "send_to_label"));
-	ui->options_combobox = GTK_WIDGET (gtk_builder_get_object (app, "options_combobox"));
 	ui->dialog = GTK_WIDGET (gtk_builder_get_object (app, "nautilus_sendto_dialog"));
 	ui->cancel_button = GTK_WIDGET (gtk_builder_get_object (app, "cancel_button"));
 	ui->send_button = GTK_WIDGET (gtk_builder_get_object (app, "send_button"));
-	ui->pack_combobox = GTK_WIDGET (gtk_builder_get_object (app, "pack_combobox"));	
-	ui->pack_entry = GTK_WIDGET (gtk_builder_get_object (app, "pack_entry"));
-	ui->pack_checkbutton = GTK_WIDGET (gtk_builder_get_object (app, "pack_checkbutton"));
-	ui->status_box = GTK_WIDGET (gtk_builder_get_object (app, "status_box"));
-	ui->status_label = GTK_WIDGET (gtk_builder_get_object (app, "status_label"));
-	ui->status_image = GTK_WIDGET (gtk_builder_get_object (app, "status_image"));
 
 	gtk_settings = gtk_settings_get_default ();
 	button_image = GTK_WIDGET (gtk_builder_get_object (app, "image1"));
@@ -560,148 +359,84 @@ nautilus_sendto_create_ui (void)
 			  G_CALLBACK (update_button_image), button_image);
 	update_button_image (gtk_settings, NULL, button_image);
 
-	gtk_combo_box_set_active (GTK_COMBO_BOX(ui->pack_combobox),
-				  g_settings_get_int (settings,
-						      NAUTILUS_SENDTO_LAST_COMPRESS));
-
-	if (file_list != NULL && file_list->next != NULL)
-		one_file = FALSE;
-	else if (file_list != NULL)
-		one_file = TRUE;
-	
-	gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), _("Files"));
-
-	if (one_file) {
-		char *filepath = NULL, *filename = NULL;
+	/* FIXME:
+	 * Set the title of the window depending on the mime-types in mime_types */
 
-		filepath = g_filename_from_uri ((char *)file_list->data,
-				NULL, NULL);
-
-		if (filepath != NULL)
-			filename = g_path_get_basename (filepath);
-		if (filename != NULL && filename[0] != '\0')
-			gtk_entry_set_text (GTK_ENTRY (ui->pack_entry), filename);
-
-		g_free (filename);
-		g_free (filepath);
-	} else {
-		char *filename = get_filename_from_list ();
-		if (filename != NULL && filename[0] != '\0') {
-			gtk_entry_set_text (GTK_ENTRY (ui->pack_entry),
-					filename);
-		}
-		g_free (filename);
-	}
-
-	set_contact_widgets (ui);
-	supports_dirs = set_model_for_options_combobox (ui);
+	set_model_for_options_treeview (ui);
 	g_signal_connect (G_OBJECT (ui->dialog), "destroy",
                           G_CALLBACK (destroy_dialog), NULL);
 	g_signal_connect (G_OBJECT (ui->cancel_button), "clicked",
 			  G_CALLBACK (destroy_dialog), NULL);
 	g_signal_connect (G_OBJECT (ui->send_button), "clicked",
 			  G_CALLBACK (send_button_cb), ui);
-	g_signal_connect (G_OBJECT (ui->pack_entry), "activate",
-			  G_CALLBACK (send_button_cb), ui);
-	g_signal_connect (G_OBJECT (ui->pack_entry), "notify::text",
-			  G_CALLBACK (pack_entry_changed_cb), ui);
-	g_signal_connect (G_OBJECT (ui->pack_checkbutton), "toggled",
-			  G_CALLBACK (toggle_pack_check), ui);
-
-	if (has_dirs == FALSE || supports_dirs != FALSE) {
-		gboolean toggle;
-
-		toggle = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton));
-		gtk_widget_set_sensitive (ui->pack_combobox, toggle);
-		gtk_widget_set_sensitive (ui->pack_entry, toggle);
-	} else {
-		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->pack_checkbutton), TRUE);
-		gtk_widget_set_sensitive (ui->pack_checkbutton, FALSE);
-	}
 
 	gtk_widget_show (ui->dialog);
-
 }
 
 static void
-nautilus_sendto_plugin_dir_process (const char *plugindir)
+nautilus_sendto_plugin_load_all (void)
 {
-	GDir *dir;
-	const char *item;
-	NstPlugin *p = NULL;
-	gboolean (*nst_init_plugin)(NstPlugin *p);
-	GError *err = NULL;
-
-	dir = g_dir_open (plugindir, 0, &err);
-
-	if (dir == NULL) {
-		g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason");
-		if (err)
-			g_error_free (err);
-	} else {
-		while ((item = g_dir_read_name(dir))) {
-			if (g_str_has_suffix (item, SOEXT)) {
-				char *module_path;
-
-				p = g_new0(NstPlugin, 1);
-				module_path = g_module_build_path (plugindir, item);
-				p->module = g_module_open (module_path, 0);
-			        if (!p->module) {
-                			g_warning ("error opening %s: %s", module_path, g_module_error ());
-					g_free (module_path);
-					continue;
-				}
-				g_free (module_path);
-
-				if (!g_module_symbol (p->module, "nst_init_plugin", (gpointer *) &nst_init_plugin)) {
-			                g_warning ("error: %s", g_module_error ());
-					g_module_close (p->module);
-					continue;
-				}
-
-				nst_init_plugin (p);
-				if (p->info->init(p)) {
-					plugin_list = g_list_append (plugin_list, p);
-				} else {
-					g_free (p);
-				}
-			}
-		}
-		g_dir_close (dir);
+	const GList *list, *l;
+	GPtrArray *activate;
+
+	activate = g_ptr_array_new ();
+	list = peas_engine_get_plugin_list (PEAS_ENGINE (engine));
+	for (l = list; l != NULL; l = l->next) {
+		PeasPluginInfo *info = l->data;
+		g_ptr_array_add (activate, (gpointer) peas_plugin_info_get_module_name (info));
 	}
+	g_ptr_array_add (activate, NULL);
+
+	peas_engine_set_loaded_plugins (PEAS_ENGINE (engine), (const char **) activate->pdata);
+	g_ptr_array_free (activate, TRUE);
 }
 
-static gboolean
+static void
 nautilus_sendto_plugin_init (void)
 {
-	if (g_file_test (UNINSTALLED_PLUGINDIR, G_FILE_TEST_IS_DIR) != FALSE) {
-		/* Try to load the local plugins */
-		GError *err = NULL;
-		GDir *dir;
-		const char *item;
-
-		dir = g_dir_open ("plugins/", 0, &err);
-		if (dir == NULL) {
-			g_warning ("Can't open the plugins dir: %s", err ? err->message : "No reason");
-			if (err)
-				g_error_free (err);
-			return FALSE;
-		}
-		while ((item = g_dir_read_name(dir))) {
-			char *plugindir;
+	GPtrArray *search_paths;
+	char **paths, *user_dir;
 
-			plugindir = g_strdup_printf ("plugins/%s/.libs/", item);
-			if (g_file_test (plugindir, G_FILE_TEST_IS_DIR) != FALSE)
-				nautilus_sendto_plugin_dir_process (plugindir);
-			g_free (plugindir);
-		}
-		g_dir_close (dir);
+	g_irepository_require (g_irepository_get_default (), "Peas", "1.0", 0, NULL);
+	/* FIXME load the uninstalled version of the bindings if needed */
+	if (g_irepository_require (g_irepository_get_default (), "NautilusSendto", "1.0", 0, NULL) == NULL) {
+		g_warning ("Failed to load NautilusSendto bindings");
 	}
 
-	if (g_list_length (plugin_list) == 0)
-		nautilus_sendto_plugin_dir_process (PLUGINDIR);
+	search_paths = g_ptr_array_new ();
+
+	/* Add uninstalled plugins */
+	if (g_file_test (UNINSTALLED_PLUGINDIR, G_FILE_TEST_IS_DIR) != FALSE) {
+		g_ptr_array_add (search_paths, "plugins/");
+		g_ptr_array_add (search_paths, "plugins/");
+	}
+
+	/* Add user plugins */
+	user_dir = g_build_filename (g_get_user_config_dir (), "nautilus-sendto", "plugins", NULL);
+	g_ptr_array_add (search_paths, user_dir);
+	g_ptr_array_add (search_paths, user_dir);
+
+	/* Add system-wide plugins */
+	g_ptr_array_add (search_paths, PLUGINDIR);
+	g_ptr_array_add (search_paths, PLUGINDIR);
 
-	return g_list_length (plugin_list) != 0;
+	/* Terminate array */
+	g_ptr_array_add (search_paths, NULL);
+
+	/* Init engine */
+	paths = (char **) g_ptr_array_free (search_paths, FALSE);
+	engine = peas_engine_new ("Nst",
+				  LIBDIR,
+				  (const gchar **) paths);
+	g_free (user_dir);
+
+	/* Create the extension set */
+	exten_set = peas_extension_set_new (PEAS_ENGINE (engine),
+					    NAUTILUS_SENDTO_TYPE_PLUGIN,
+					    NULL);
+
+	/* Load all the plugins now */
+	nautilus_sendto_plugin_load_all ();
 }
 
 static char *
@@ -748,21 +483,59 @@ escape_ampersands_and_commas (const char *url)
 }
 
 static void
+collate_mimetypes (const char *key,
+		   gpointer    value,
+		   GPtrArray  *array)
+{
+	g_ptr_array_add (array, g_strdup (key));
+}
+
+static void
 nautilus_sendto_init (void)
 {
+	GHashTable *ht;
+	GPtrArray *array;
 	int i;
 
-	if (g_module_supported() == FALSE)
-		g_error ("Could not initialize gmodule support");
+	ht = g_hash_table_new_full (g_str_hash, g_direct_equal,
+				    g_free, NULL);
 
+	/* Clean up the URIs passed, and collect the mime-types of
+	 * the files */
 	for (i = 0; filenames != NULL && filenames[i] != NULL; i++) {
 		GFile *file;
 		char *filename, *escaped, *uri;
+		GFileInfo *info;
+		const char *mimetype;
 
+		/* We need a filename */
 		file = g_file_new_for_commandline_arg (filenames[i]);
 		filename = g_file_get_path (file);
-		if (filename == NULL)
+		if (filename == NULL) {
+			g_object_unref (file);
 			continue;
+		}
+
+		/* Get the mime-type, and whether the file is readable */
+		info = g_file_query_info (file,
+					  G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE","G_FILE_ATTRIBUTE_ACCESS_CAN_READ,
+					  G_FILE_QUERY_INFO_NONE,
+					  NULL,
+					  NULL);
+		g_object_unref (file);
+
+		if (info == NULL)
+			continue;
+
+		if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ) == FALSE) {
+			g_message ("Foobar is not readable");
+			g_object_unref (info);
+			continue;
+		}
+		mimetype = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
+		g_hash_table_insert (ht, g_strdup (mimetype), GINT_TO_POINTER (1));
+
+		g_object_unref (info);
 
 		if (g_file_test (filename, G_FILE_TEST_IS_DIR) != FALSE)
 			has_dirs = TRUE;
@@ -780,11 +553,20 @@ nautilus_sendto_init (void)
 	}
 
 	if (file_list == NULL) {
+		/* FIXME, this needs to be done in UI now */
 		g_print (_("Expects URIs or filenames to be passed as options\n"));
 		exit (1);
 	}
 
 	file_list = g_list_reverse (file_list);
+
+	/* Collate the mime-types */
+	array = g_ptr_array_new ();
+	g_hash_table_foreach (ht, (GHFunc) collate_mimetypes, array);
+	g_hash_table_destroy (ht);
+
+	g_ptr_array_add (array, NULL);
+	mime_types = (char **) g_ptr_array_free (array, FALSE);
 }
 
 int main (int argc, char **argv)
@@ -808,30 +590,12 @@ int main (int argc, char **argv)
 
 	settings = g_settings_new ("org.gnome.Nautilus.Sendto");
 	nautilus_sendto_init ();
-	if (nautilus_sendto_plugin_init () == FALSE) {
-		GtkWidget *error_dialog;
-
-		error_dialog =
-			gtk_message_dialog_new (NULL,
-						GTK_DIALOG_MODAL,
-						GTK_MESSAGE_ERROR,
-						GTK_BUTTONS_OK,
-						_("Could not load any plugins."));
-		gtk_message_dialog_format_secondary_text
-			(GTK_MESSAGE_DIALOG (error_dialog),
-			 _("Please verify your installation"));
-
-		gtk_window_set_title (GTK_WINDOW (error_dialog), ""); /* as per HIG */
-		gtk_container_set_border_width (GTK_CONTAINER (error_dialog), 5);
-		gtk_dialog_set_default_response (GTK_DIALOG (error_dialog),
-						 GTK_RESPONSE_OK);
-		gtk_dialog_run (GTK_DIALOG (error_dialog));
-		return 1;
-	}
+	nautilus_sendto_plugin_init ();
 	nautilus_sendto_create_ui ();
 
 	gtk_main ();
 	g_object_unref(settings);
+	g_strfreev (mime_types);
 
 	return 0;
 }
diff --git a/src/nautilus-sendto.ui b/src/nautilus-sendto.ui
index e842dfe..1e94ac9 100644
--- a/src/nautilus-sendto.ui
+++ b/src/nautilus-sendto.ui
@@ -1,8 +1,10 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
+  <!-- interface-requires gtk+ 2.12 -->
+  <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkListStore" id="model1">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -19,473 +21,156 @@
   </object>
   <object class="GtkDialog" id="nautilus_sendto_dialog">
     <property name="border_width">5</property>
-    <property name="width_request">370</property>
-    <property name="visible">True</property>
-    <property name="title" translatable="yes">Send To...</property>
-    <property name="type">GTK_WINDOW_TOPLEVEL</property>
-    <property name="window_position">GTK_WIN_POS_CENTER</property>
-    <property name="modal">False</property>
-    <property name="resizable">True</property>
-    <property name="destroy_with_parent">False</property>
-    <property name="decorated">True</property>
-    <property name="skip_taskbar_hint">False</property>
-    <property name="skip_pager_hint">False</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
-    <property name="focus_on_map">True</property>
-    <property name="urgency_hint">False</property>
+    <property name="default_width">500</property>
+    <property name="default_height">300</property>
+    <property name="type_hint">normal</property>
     <property name="has_separator">False</property>
-    <property name="icon_name">document-send</property>
     <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox1">
+      <object class="GtkVBox" id="dialog-vbox2">
         <property name="visible">True</property>
-        <property name="homogeneous">False</property>
         <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area1">
+        <child>
+          <placeholder/>
+        </child>
+        <child>
+          <object class="GtkHPaned" id="hpaned1">
             <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <property name="can_focus">True</property>
+            <property name="position">200</property>
+            <property name="position_set">True</property>
             <child>
-              <object class="GtkButton" id="cancel_button">
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
                 <property name="visible">True</property>
-                <property name="can_default">True</property>
                 <property name="can_focus">True</property>
-                <property name="label">gtk-cancel</property>
-                <property name="use_stock">True</property>
-                <property name="relief">GTK_RELIEF_NORMAL</property>
-                <property name="focus_on_click">True</property>
+                <property name="hscrollbar_policy">automatic</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="options_treeview">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="headers_visible">False</property>
+                  </object>
+                </child>
               </object>
+              <packing>
+                <property name="resize">False</property>
+                <property name="shrink">True</property>
+              </packing>
             </child>
             <child>
-              <object class="GtkButton" id="send_button">
+              <object class="GtkHBox" id="hbox_contacts_widgets">
                 <property name="visible">True</property>
-                <property name="can_default">True</property>
-                <property name="can_focus">True</property>
-                <property name="relief">GTK_RELIEF_NORMAL</property>
-                <property name="focus_on_click">True</property>
+                <property name="spacing">12</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment1">
+                  <object class="GtkNotebook" id="contacts_notebook">
                     <property name="visible">True</property>
-                    <property name="xalign">0.5</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xscale">0</property>
-                    <property name="yscale">0</property>
-                    <property name="top_padding">0</property>
-                    <property name="bottom_padding">0</property>
-                    <property name="left_padding">0</property>
-                    <property name="right_padding">0</property>
+                    <property name="can_focus">True</property>
+                    <property name="show_border">False</property>
                     <child>
-                      <object class="GtkHBox" id="hbox2">
-                        <property name="visible">True</property>
-                        <property name="homogeneous">False</property>
-                        <property name="spacing">2</property>
-                        <child>
-                          <object class="GtkImage" id="image1">
-                            <property name="visible">True</property>
-                            <property name="icon_name">document-send</property>
-                            <property name="icon_size">4</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
-                          </object>
-                          <packing>
-                            <property name="padding">0</property>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="label5">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">_Send</property>
-                            <property name="use_underline">True</property>
-                            <property name="use_markup">False</property>
-                            <property name="justify">GTK_JUSTIFY_LEFT</property>
-                            <property name="wrap">False</property>
-                            <property name="selectable">False</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
-                            <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                            <property name="width_chars">-1</property>
-                            <property name="single_line_mode">False</property>
-                            <property name="angle">0</property>
-                          </object>
-                          <packing>
-                            <property name="padding">0</property>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
-                          </packing>
-                        </child>
-                      </object>
+                      <placeholder/>
                     </child>
                   </object>
+                  <packing>
+                    <property name="position">0</property>
+                  </packing>
                 </child>
               </object>
+              <packing>
+                <property name="resize">True</property>
+                <property name="shrink">True</property>
+              </packing>
             </child>
           </object>
           <packing>
-            <property name="padding">0</property>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">GTK_PACK_END</property>
+            <property name="position">2</property>
           </packing>
         </child>
-        <child>
-          <object class="GtkVBox" id="vbox1">
-            <property name="border_width">5</property>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area2">
             <property name="visible">True</property>
-            <property name="homogeneous">False</property>
-            <property name="spacing">18</property>
+            <property name="layout_style">end</property>
             <child>
-              <object class="GtkVBox" id="vbox2">
+              <object class="GtkButton" id="cancel_button">
+                <property name="label">gtk-cancel</property>
                 <property name="visible">True</property>
-                <property name="homogeneous">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="label6">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">&lt;b&gt;Destination&lt;/b&gt;</property>
-                    <property name="use_underline">False</property>
-                    <property name="use_markup">True</property>
-                    <property name="justify">GTK_JUSTIFY_LEFT</property>
-                    <property name="wrap">False</property>
-                    <property name="selectable">False</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xpad">0</property>
-                    <property name="ypad">0</property>
-                    <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                    <property name="width_chars">-1</property>
-                    <property name="single_line_mode">False</property>
-                    <property name="angle">0</property>
-                  </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkAlignment" id="alignment2">
-                    <property name="visible">True</property>
-                    <property name="xalign">0.5</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xscale">1</property>
-                    <property name="yscale">1</property>
-                    <property name="top_padding">0</property>
-                    <property name="bottom_padding">0</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">0</property>
-                    <child>
-                      <object class="GtkTable" id="table2">
-                        <property name="visible">True</property>
-                        <property name="n_rows">2</property>
-                        <property name="n_columns">2</property>
-                        <property name="homogeneous">False</property>
-                        <property name="row_spacing">6</property>
-                        <property name="column_spacing">12</property>
-                        <child>
-                          <object class="GtkLabel" id="label3">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Send _as:</property>
-                            <property name="use_underline">True</property>
-                            <property name="use_markup">False</property>
-                            <property name="justify">GTK_JUSTIFY_LEFT</property>
-                            <property name="wrap">False</property>
-                            <property name="selectable">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
-                            <property name="mnemonic_widget">options_combobox</property>
-                            <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                            <property name="width_chars">-1</property>
-                            <property name="single_line_mode">False</property>
-                            <property name="angle">0</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="right_attach">1</property>
-                            <property name="top_attach">0</property>
-                            <property name="bottom_attach">1</property>
-                            <property name="x_options">fill</property>
-                            <property name="y_options"/>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkComboBox" id="options_combobox">
-                            <property name="visible">True</property>
-                            <property name="add_tearoffs">False</property>
-                            <property name="focus_on_click">True</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="top_attach">0</property>
-                            <property name="bottom_attach">1</property>
-                            <property name="y_options">fill</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkLabel" id="send_to_label">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Send t_o:</property>
-                            <property name="use_underline">True</property>
-                            <property name="use_markup">False</property>
-                            <property name="justify">GTK_JUSTIFY_LEFT</property>
-                            <property name="wrap">False</property>
-                            <property name="selectable">False</property>
-                            <property name="xalign">0</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
-                            <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                            <property name="width_chars">-1</property>
-                            <property name="single_line_mode">False</property>
-                            <property name="angle">0</property>
-                          </object>
-                          <packing>
-                            <property name="left_attach">0</property>
-                            <property name="right_attach">1</property>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">fill</property>
-                            <property name="y_options"/>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkHBox" id="hbox_contacts_widgets">
-                            <property name="visible">True</property>
-                            <property name="homogeneous">False</property>
-                            <property name="spacing">12</property>
-                            <child>
-                              <placeholder/>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="left_attach">1</property>
-                            <property name="right_attach">2</property>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">fill</property>
-                            <property name="y_options">fill</property>
-                          </packing>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                  </packing>
-                </child>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
               </object>
               <packing>
-                <property name="padding">6</property>
                 <property name="expand">False</property>
-                <property name="fill">True</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
               </packing>
             </child>
             <child>
-              <object class="GtkVBox" id="vbox3">
+              <object class="GtkButton" id="send_button">
                 <property name="visible">True</property>
-                <property name="homogeneous">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="label7">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">&lt;b&gt;Compression&lt;/b&gt;</property>
-                    <property name="use_underline">False</property>
-                    <property name="use_markup">True</property>
-                    <property name="justify">GTK_JUSTIFY_LEFT</property>
-                    <property name="wrap">False</property>
-                    <property name="selectable">False</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xpad">0</property>
-                    <property name="ypad">0</property>
-                    <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                    <property name="width_chars">-1</property>
-                    <property name="single_line_mode">False</property>
-                    <property name="angle">0</property>
-                  </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
-                </child>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">True</property>
                 <child>
-                  <object class="GtkAlignment" id="alignment3">
+                  <object class="GtkAlignment" id="alignment1">
                     <property name="visible">True</property>
-                    <property name="xalign">0.5</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xscale">1</property>
-                    <property name="yscale">1</property>
-                    <property name="top_padding">0</property>
-                    <property name="bottom_padding">0</property>
-                    <property name="left_padding">12</property>
-                    <property name="right_padding">0</property>
+                    <property name="xscale">0</property>
+                    <property name="yscale">0</property>
                     <child>
-                      <object class="GtkVBox" id="vbox4">
+                      <object class="GtkHBox" id="hbox2">
                         <property name="visible">True</property>
-                        <property name="homogeneous">False</property>
-                        <property name="spacing">6</property>
+                        <property name="spacing">2</property>
                         <child>
-                          <object class="GtkCheckButton" id="pack_checkbutton">
-                            <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="label" translatable="yes">Send _packed in:</property>
-                            <property name="use_underline">True</property>
-                            <property name="relief">GTK_RELIEF_NORMAL</property>
-                            <property name="focus_on_click">True</property>
+                          <object class="GtkSpinner" id="spinner">
+                            <property name="visible">False</property>
                             <property name="active">False</property>
-                            <property name="inconsistent">False</property>
-                            <property name="draw_indicator">True</property>
                           </object>
                           <packing>
-                            <property name="padding">0</property>
                             <property name="expand">False</property>
                             <property name="fill">False</property>
+                            <property name="position">1</property>
                           </packing>
+                          <placeholder/>
                         </child>
                         <child>
-                          <object class="GtkAlignment" id="alignment4">
+                          <object class="GtkImage" id="image1">
                             <property name="visible">True</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xscale">1</property>
-                            <property name="yscale">1</property>
-                            <property name="top_padding">0</property>
-                            <property name="bottom_padding">0</property>
-                            <property name="left_padding">12</property>
-                            <property name="right_padding">0</property>
-                            <child>
-                              <object class="GtkHBox" id="hbox4">
-                                <property name="visible">True</property>
-                                <property name="homogeneous">False</property>
-                                <property name="spacing">6</property>
-                                <child>
-                                  <object class="GtkEntry" id="pack_entry">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="editable">True</property>
-                                    <property name="visibility">True</property>
-                                    <property name="max_length">0</property>
-                                    <property name="text" translatable="yes"/>
-                                    <property name="has_frame">True</property>
-                                    <property name="invisible_char">*</property>
-                                    <property name="activates_default">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="padding">0</property>
-                                    <property name="expand">True</property>
-                                    <property name="fill">True</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkComboBox" id="pack_combobox">
-                                    <property name="visible">True</property>
-                                    <property name="add_tearoffs">False</property>
-                                    <property name="focus_on_click">True</property>
-                                    <property name="model">model1</property>
-                                    <child>
-                                      <object class="GtkCellRendererText" id="renderer1"/>
-                                      <attributes>
-                                        <attribute name="text">0</attribute>
-                                      </attributes>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="padding">0</property>
-                                    <property name="expand">True</property>
-                                    <property name="fill">True</property>
-                                  </packing>
-                                </child>
-                              </object>
-                            </child>
+                            <property name="icon_name">document-send</property>
                           </object>
                           <packing>
-                            <property name="padding">0</property>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label5">
+                            <property name="visible">True</property>
+                            <property name="label" translatable="yes">_Send</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">2</property>
                           </packing>
                         </child>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="padding">0</property>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkHBox" id="status_box">
-                <property name="homogeneous">False</property>
-                <property name="spacing">12</property>
-                <child>
-                  <object class="GtkImage" id="status_image">
-                    <property name="stock">gtk-dialog-error</property>
-                    <property name="icon_size">4</property>
-                    <property name="xalign">0.5</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xpad">0</property>
-                    <property name="ypad">0</property>
-                  </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkLabel" id="status_label">
-                    <property name="visible">True</property>
-                    <property name="label"> </property>
-                    <property name="use_underline">False</property>
-                    <property name="use_markup">False</property>
-                    <property name="justify">GTK_JUSTIFY_LEFT</property>
-                    <property name="wrap">False</property>
-                    <property name="selectable">False</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xpad">0</property>
-                    <property name="ypad">0</property>
-                    <property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property>
-                    <property name="width_chars">-1</property>
-                    <property name="single_line_mode">False</property>
-                    <property name="angle">0</property>
-                  </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
-                  </packing>
                 </child>
               </object>
               <packing>
-                <property name="padding">0</property>
                 <property name="expand">False</property>
-                <property name="fill">True</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
               </packing>
             </child>
           </object>
           <packing>
-            <property name="padding">0</property>
             <property name="expand">False</property>
-            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
           </packing>
         </child>
       </object>
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 8d51b6a..1f4710f 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -1,13 +1,44 @@
-SUBDIRS = . $(PLUGINS)
+SUBDIRS = . removable-devices evolution
+#SUBDIRS = . $(PLUGINS)
 DIST_SUBDIRS = $(ALL_PLUGINS)
 
 NST_COMMON_SOURCES = nst-common.c nst-common.h
 
-if HAVE_GIO
 noinst_LTLIBRARIES = libnstcommon.la
 libnstcommon_la_SOURCES = $(NST_COMMON_SOURCES)
-libnstcommon_la_CFLAGS = $(GIO_CFLAGS)
-libnstcommon_la_LIBADD = $(GIO_LIBS)
-endif
+libnstcommon_la_CFLAGS = $(NAUTILUS_SENDTO_CFLAGS)
+libnstcommon_la_LIBADD = $(NAUTILUS_SENDTO_LIBS)
 
 EXTRA_DIST = $(NST_COMMON_SOURCES)
+
+nautilus_sendto_includedir = $(includedir)/nautilus-sendto/
+nautilus_sendto_include_HEADERS = nautilus-sendto-plugin.h
+
+lib_LTLIBRARIES = libnautilussendto-1.0.la
+libnautilussendto_1_0_la_SOURCES = nautilus-sendto-plugin.h nautilus-sendto-plugin.c
+libnautilussendto_1_0_la_LIBADD = $(NAUTILUS_SENDTO_LIBS)
+libnautilussendto_1_0_la_CFLAGS = $(NAUTILUS_SENDTO_CFLAGS)
+
+if HAVE_INTROSPECTION
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS = NautilusSendto-1.0.gir
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(top_builddir)/src --warn-all
+INTROSPECTION_COMPILER_ARGS = --includedir=$(top_srcdir)/libpeas
+
+introspection_sources = $(libnautilussendto_1_0_la_SOURCES)
+
+NautilusSendto-1.0.gir: libnautilussendto-1.0.la
+NautilusSendto_1_0_gir_INCLUDES = GObject-2.0 Gtk-3.0 Peas-1.0
+NautilusSendto_1_0_gir_CFLAGS = $(NAUTILUS_SENDTO_CFLAGS) -I$(top_srcdir)
+NautilusSendto_1_0_gir_LIBS = libnautilussendto-1.0.la
+NautilusSendto_1_0_gir_FILES = $(addprefix $(srcdir)/,$(introspection_sources))
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES = $(gir_DATA) $(typelib_DATA)
+endif
+
diff --git a/src/plugins/evolution/Makefile.am b/src/plugins/evolution/Makefile.am
index 8705a9b..de4e539 100644
--- a/src/plugins/evolution/Makefile.am
+++ b/src/plugins/evolution/Makefile.am
@@ -1,10 +1,14 @@
 plugindir = $(libdir)/nautilus-sendto/plugins
 
+plugin_in_files = evolution.nst-plugin.in
+%.nst-plugin: %.nst-plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+plugin_DATA = evolution.nst-plugin
+
 INCLUDES =                                      \
         -DDATADIR=\"$(datadir)\"                \
         -DICONDIR=\"$(icondir)\"                \
 	-DLOCALEDIR="\"$(datadir)/locale\""	\
-        -I$(top_srcdir)/src                     \
+        -I$(top_srcdir)/src/plugins             \
         -I$(top_builddir)                       \
         $(NAUTILUS_SENDTO_CFLAGS)               \
 	$(NST_EBOOK_CFLAGS)			\
@@ -28,8 +32,8 @@ plugin_LTLIBRARIES = libnstevolution.la
 
 libnstevolution_la_SOURCES = evolution.c $(CLA_FILES) $(MARSHALFILES)
 libnstevolution_la_LDFLAGS = -module -avoid-version
-libnstevolution_la_LIBADD = $(NST_EBOOK_LIBS) $(NAUTILUS_SENDTO_LIBS)
+libnstevolution_la_LIBADD = $(NST_EBOOK_LIBS) $(NAUTILUS_SENDTO_LIBS) $(builddir)/../libnstcommon.la $(builddir)/../libnautilussendto-1.0.la
 
-EXTRA_DIST = $(CLA_FILES)
+EXTRA_DIST = $(CLA_FILES) $(plugin_in_files)
 CLEANFILES = econtactentry-marshal.c econtactentry-marshal.h
 
diff --git a/src/plugins/evolution/evolution.c b/src/plugins/evolution/evolution.c
index 7feb305..8396c0f 100644
--- a/src/plugins/evolution/evolution.c
+++ b/src/plugins/evolution/evolution.c
@@ -1,8 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* 
+/*
  * Copyright (C) 2004 Roberto Majadas
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -19,6 +17,7 @@
  * Boston, MA 02110-1301  USA.
  *
  * Author:  Roberto Majadas <roberto majadas openshine com>
+ *          Bastien Nocera <hadess hadess net>
  */
 
 #include "config.h"
@@ -27,12 +26,17 @@
 #include <glib/gi18n-lib.h>
 #include <string.h>
 #include "nautilus-sendto-plugin.h"
+#include "nst-common.h"
 
-#define GCONF_COMPLETION "/apps/evolution/addressbook"
-#define GCONF_COMPLETION_SOURCES GCONF_COMPLETION "/sources"
-#define DEFAULT_MAILTO "/desktop/gnome/url-handlers/mailto/command"
+#define EVOLUTION_TYPE_PLUGIN         (evolution_plugin_get_type ())
+#define EVOLUTION_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EVOLUTION_TYPE_PLUGIN, EvolutionPlugin))
+#define EVOLUTION_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EVOLUTION_TYPE_PLUGIN, EvolutionPlugin))
+#define EVOLUTION_IS_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EVOLUTION_TYPE_PLUGIN))
+#define EVOLUTION_IS_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EVOLUTION_TYPE_PLUGIN))
+#define EVOLUTION_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EVOLUTION_TYPE_PLUGIN, EvolutionPluginClass))
 
-#define CONTACT_FORMAT "%s <%s>"
+typedef struct _EvolutionPlugin       EvolutionPlugin;
+typedef struct _EvolutionPluginClass  EvolutionPluginClass;
 
 typedef enum {
 	MAILER_UNKNOWN,
@@ -42,10 +46,30 @@ typedef enum {
 	MAILER_THUNDERBIRD,
 } MailerType;
 
-static char *mail_cmd = NULL;
-static MailerType type = MAILER_UNKNOWN;
-static char *email = NULL;
-static char *name = NULL;
+struct _EvolutionPlugin {
+	PeasExtensionBase parent_instance;
+
+	GtkWidget *vbox;
+	GtkWidget *entry;
+	GtkWidget *packer;
+
+	char *mail_cmd;
+	MailerType type;
+	char *email;
+	char *name;
+};
+
+struct _EvolutionPluginClass {
+	PeasExtensionBaseClass parent_class;
+};
+
+NAUTILUS_PLUGIN_REGISTER(EVOLUTION_TYPE_PLUGIN, EvolutionPlugin, evolution_plugin)
+
+#define GCONF_COMPLETION "/apps/evolution/addressbook"
+#define GCONF_COMPLETION_SOURCES GCONF_COMPLETION "/sources"
+#define DEFAULT_MAILTO "/desktop/gnome/url-handlers/mailto/command"
+
+#define CONTACT_FORMAT "%s <%s>"
 
 static char *
 get_evo_cmd (void)
@@ -62,7 +86,6 @@ get_evo_cmd (void)
 		NULL};
 	guint i;
 
-	
 	for (i = 0; cmds[i] != NULL; i++) {
 		tmp = g_find_program_in_path (cmds[i]);
 		if (tmp != NULL)
@@ -77,94 +100,114 @@ get_evo_cmd (void)
 	return retval;
 }
 
-static gboolean
-init (NstPlugin *plugin)
+static void
+evolution_plugin_init (EvolutionPlugin *p)
 {
 	GConfClient *client;
 
-	g_print ("Init evolution plugin\n");
-	
 	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
+	p->type = MAILER_UNKNOWN;
+	p->email = NULL;
+	p->name = NULL;
+
 	client = gconf_client_get_default ();
-	mail_cmd = gconf_client_get_string (client, DEFAULT_MAILTO, NULL);
+	p->mail_cmd = gconf_client_get_string (client, DEFAULT_MAILTO, NULL);
 	g_object_unref (client);
 
-	if (mail_cmd == NULL || *mail_cmd == '\0') {
-		g_free (mail_cmd);
-		mail_cmd = get_evo_cmd ();
-		type = MAILER_EVO;
+	if (p->mail_cmd == NULL || *p->mail_cmd == '\0') {
+		g_free (p->mail_cmd);
+		p->mail_cmd = get_evo_cmd ();
+		p->type = MAILER_EVO;
 	} else {
 		/* Find what the default mailer is */
-		if (strstr (mail_cmd, "balsa"))
-			type = MAILER_BALSA;
-		else if (strstr (mail_cmd, "thunder") || strstr (mail_cmd, "seamonkey")) {
+		if (strstr (p->mail_cmd, "balsa"))
+			p->type = MAILER_BALSA;
+		else if (strstr (p->mail_cmd, "thunder") || strstr (p->mail_cmd, "seamonkey")) {
 			char **strv;
 
-			type = MAILER_THUNDERBIRD;
+			p->type = MAILER_THUNDERBIRD;
 
 			/* Thunderbird sucks, see
 			 * https://bugzilla.gnome.org/show_bug.cgi?id=614222 */
-			strv = g_strsplit (mail_cmd, " ", -1);
-			g_free (mail_cmd);
-			mail_cmd = g_strdup_printf ("%s %%s", strv[0]);
+			strv = g_strsplit (p->mail_cmd, " ", -1);
+			g_free (p->mail_cmd);
+			p->mail_cmd = g_strdup_printf ("%s %%s", strv[0]);
 			g_strfreev (strv);
-		} else if (strstr (mail_cmd, "sylpheed") || strstr (mail_cmd, "claws"))
-			type = MAILER_SYLPHEED;
-		else if (strstr (mail_cmd, "anjal"))
-			type = MAILER_EVO;
+		} else if (strstr (p->mail_cmd, "sylpheed") || strstr (p->mail_cmd, "claws"))
+			p->type = MAILER_SYLPHEED;
+		else if (strstr (p->mail_cmd, "anjal"))
+			p->type = MAILER_EVO;
 	}
+}
 
-	if (mail_cmd == NULL)
+static gboolean
+evolution_plugin_supports_mime_types (NautilusSendtoPlugin *plugin,
+				      const char          **mime_types)
+{
+	EvolutionPlugin *p;
+
+	p = EVOLUTION_PLUGIN (plugin);
+
+	if (p->mail_cmd == NULL)
 		return FALSE;
 
+	//FIXME check for types and setup the packer
+
 	return TRUE;
 }
 
 static void
-contacts_selected_cb (GtkWidget *entry, EContact *contact, const char *identifier, NstPlugin *plugin)
+contacts_selected_cb (GtkWidget       *entry,
+		      EContact        *contact,
+		      const char      *identifier,
+		      EvolutionPlugin *p)
 {
 	char *text;
 
-	g_free (email);
-	email = NULL;
+	g_free (p->email);
+	p->email = NULL;
 
 	if (identifier != NULL)
-		email = g_strdup (identifier);
+		p->email = g_strdup (identifier);
 	else
-		email = e_contact_get (contact, E_CONTACT_EMAIL_1);
+		p->email = e_contact_get (contact, E_CONTACT_EMAIL_1);
 
-	g_free (name);
-	name = NULL;
+	g_free (p->name);
+	p->name = NULL;
 
-	name = e_contact_get (contact, E_CONTACT_FULL_NAME);
-	if (name == NULL) {
-		name = e_contact_get (contact, E_CONTACT_NICKNAME);
-		if (name == NULL)
-			name = e_contact_get (contact, E_CONTACT_ORG);
+	p->name = e_contact_get (contact, E_CONTACT_FULL_NAME);
+	if (p->name == NULL) {
+		p->name = e_contact_get (contact, E_CONTACT_NICKNAME);
+		if (p->name == NULL)
+			p->name = e_contact_get (contact, E_CONTACT_ORG);
 	}
-	if (name != NULL) {
-		text = g_strdup_printf (CONTACT_FORMAT, (char*) name, email);
+	if (p->name != NULL) {
+		text = g_strdup_printf (CONTACT_FORMAT, (char*) p->name, p->email);
 		gtk_entry_set_text (GTK_ENTRY (entry), text);
 		g_free (text);
 	} else
-		gtk_entry_set_text (GTK_ENTRY (entry), email);
+		gtk_entry_set_text (GTK_ENTRY (entry), p->email);
 }
 
 static void
-state_change_cb (GtkWidget *entry, gboolean state, gpointer data)
+state_change_cb (GtkWidget       *entry,
+		 gboolean         state,
+		 EvolutionPlugin *p)
 {
 	if (state == FALSE) {
-		g_free (email);
-		email = NULL;
-		g_free (name);
-		name = NULL;
+		g_free (p->email);
+		p->email = NULL;
+		g_free (p->name);
+		p->name = NULL;
 	}
 }
 
 static void
-error_cb (EContactEntry *entry_widget, const char *error, NstPlugin *plugin)
+error_cb (EContactEntry   *entry_widget,
+	  const char      *error,
+	  EvolutionPlugin *plugin)
 {
 	g_warning ("An error occurred: %s", error);
 }
@@ -182,8 +225,10 @@ add_sources (EContactEntry *entry)
 }
 
 static void
-sources_changed_cb (GConfClient *client, guint cnxn_id,
-		GConfEntry *entry, EContactEntry *entry_widget)
+sources_changed_cb (GConfClient   *client,
+		    guint          cnxn_id,
+		    GConfEntry    *entry,
+		    EContactEntry *entry_widget)
 {
 	add_sources (entry_widget);
 }
@@ -201,40 +246,56 @@ setup_source_changes (EContactEntry *entry)
 			entry, NULL, NULL);
 }
 
-static
-GtkWidget* get_contacts_widget (NstPlugin *plugin)
+static GtkWidget *
+evolution_plugin_get_widget (NautilusSendtoPlugin *plugin,
+			     GList                *file_list)
 {
-	GtkWidget *entry;
+	EvolutionPlugin *p;
+	GtkWidget *alignment;
 
-	entry = e_contact_entry_new ();
-	g_signal_connect (G_OBJECT (entry), "contact-selected",
+	p = EVOLUTION_PLUGIN (plugin);
+	p->entry = e_contact_entry_new ();
+	g_signal_connect (G_OBJECT (p->entry), "contact-selected",
 			  G_CALLBACK (contacts_selected_cb), plugin);
-	g_signal_connect (G_OBJECT (entry), "state-change",
-			  G_CALLBACK (state_change_cb), NULL);
-	g_signal_connect (G_OBJECT (entry), "error",
+	g_signal_connect (G_OBJECT (p->entry), "state-change",
+			  G_CALLBACK (state_change_cb), plugin);
+	g_signal_connect (G_OBJECT (p->entry), "error",
 			  G_CALLBACK (error_cb), plugin);
 
-	add_sources (E_CONTACT_ENTRY (entry));
-	setup_source_changes (E_CONTACT_ENTRY (entry));
+	add_sources (E_CONTACT_ENTRY (p->entry));
+	setup_source_changes (E_CONTACT_ENTRY (p->entry));
+
+	p->vbox = gtk_vbox_new (FALSE, 8);
+	gtk_box_pack_start (GTK_BOX (p->vbox), p->entry, FALSE, FALSE, 0);
+
+	alignment = gtk_alignment_new (0.0, 1.0, 1.0, 0.0);
+	p->packer = nst_pack_widget_new ();
+	nst_pack_widget_set_from_names (NST_PACK_WIDGET (p->packer), file_list);
+	gtk_container_add (GTK_CONTAINER (alignment), p->packer);
+	gtk_box_pack_start (GTK_BOX (p->vbox), alignment, TRUE, TRUE, 0);
 
-	return entry;
+	gtk_widget_show_all (p->vbox);
+
+	return p->vbox;
 }
 
 static void
-get_evo_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+get_evo_mailto (EvolutionPlugin *p,
+		GString         *mailto,
+		GList           *file_list)
 {
 	GList *l;
 
 	g_string_append (mailto, "mailto:";);
-	if (email != NULL) {
-		if (name != NULL)
-			g_string_append_printf (mailto, "\""CONTACT_FORMAT"\"", name, email);
+	if (p->email != NULL) {
+		if (p->name != NULL)
+			g_string_append_printf (mailto, "\""CONTACT_FORMAT"\"", p->name, p->email);
 		else
-			g_string_append_printf (mailto, "%s", email);
+			g_string_append_printf (mailto, "%s", p->email);
 	} else {
 		const char *text;
 
-		text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+		text = gtk_entry_get_text (GTK_ENTRY (p->entry));
 		if (text != NULL && *text != '\0')
 			g_string_append_printf (mailto, "\"%s\"", text);
 		else
@@ -247,21 +308,23 @@ get_evo_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
 }
 
 static void
-get_balsa_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+get_balsa_mailto (EvolutionPlugin *p,
+		  GString         *mailto,
+		  GList           *file_list)
 {
 	GList *l;
 
-	if (strstr (mail_cmd, " -m ") == NULL && strstr (mail_cmd, " --compose=") == NULL)
+	if (strstr (p->mail_cmd, " -m ") == NULL && strstr (p->mail_cmd, " --compose=") == NULL)
 		g_string_append (mailto, " --compose=");
-	if (email != NULL) {
-		if (name != NULL)
-			g_string_append_printf (mailto, "\""CONTACT_FORMAT"\"", name, email);
+	if (p->email != NULL) {
+		if (p->name != NULL)
+			g_string_append_printf (mailto, "\""CONTACT_FORMAT"\"", p->name, p->email);
 		else
-			g_string_append_printf (mailto, "%s", email);
+			g_string_append_printf (mailto, "%s", p->email);
 	} else {
 		const char *text;
 
-		text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+		text = gtk_entry_get_text (GTK_ENTRY (p->entry));
 		if (text != NULL && *text != '\0')
 			g_string_append_printf (mailto, "\"%s\"", text);
 		else
@@ -274,20 +337,22 @@ get_balsa_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
 }
 
 static void
-get_thunderbird_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+get_thunderbird_mailto (EvolutionPlugin *p,
+			GString         *mailto,
+			GList           *file_list)
 {
 	GList *l;
 
 	g_string_append (mailto, "-compose \"");
-	if (email != NULL) {
-		if (name != NULL)
-			g_string_append_printf (mailto, "to='"CONTACT_FORMAT"',", name, email);
+	if (p->email != NULL) {
+		if (p->name != NULL)
+			g_string_append_printf (mailto, "to='"CONTACT_FORMAT"',", p->name, p->email);
 		else
-			g_string_append_printf (mailto, "to='%s',", email);
+			g_string_append_printf (mailto, "to='%s',", p->email);
 	} else {
 		const char *text;
 
-		text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+		text = gtk_entry_get_text (GTK_ENTRY (p->entry));
 		if (text != NULL && *text != '\0')
 			g_string_append_printf (mailto, "to='%s',", text);
 	}
@@ -299,20 +364,22 @@ get_thunderbird_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_
 }
 
 static void
-get_sylpheed_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_list)
+get_sylpheed_mailto (EvolutionPlugin *p,
+		     GString         *mailto,
+		     GList           *file_list)
 {
 	GList *l;
 
 	g_string_append (mailto, "--compose ");
-	if (email != NULL) {
-		if (name != NULL)
-			g_string_append_printf (mailto, "\""CONTACT_FORMAT"\" ", name, email);
+	if (p->email != NULL) {
+		if (p->name != NULL)
+			g_string_append_printf (mailto, "\""CONTACT_FORMAT"\" ", p->name, p->email);
 		else
-			g_string_append_printf (mailto, "%s ", email);
+			g_string_append_printf (mailto, "%s ", p->email);
 	} else {
 		const char *text;
 
-		text = gtk_entry_get_text (GTK_ENTRY (contact_widget));
+		text = gtk_entry_get_text (GTK_ENTRY (p->entry));
 		if (text != NULL && *text != '\0')
 			g_string_append_printf (mailto, "\"%s\" ", text);
 		else
@@ -325,33 +392,35 @@ get_sylpheed_mailto (GtkWidget *contact_widget, GString *mailto, GList *file_lis
 }
 
 static gboolean
-send_files (NstPlugin *plugin,
-	    GtkWidget *contact_widget,
-	    GList *file_list)
+evolution_plugin_send_files (NautilusSendtoPlugin *plugin,
+			     GList                *file_list)
 {
+	EvolutionPlugin *p;
 	gchar *cmd;
 	GString *mailto;
 
+	p = EVOLUTION_PLUGIN (plugin);
+
 	mailto = g_string_new ("");
-	switch (type) {
+	switch (p->type) {
 	case MAILER_BALSA:
-		get_balsa_mailto (contact_widget, mailto, file_list);
+		get_balsa_mailto (p, mailto, file_list);
 		break;
 	case MAILER_SYLPHEED:
-		get_sylpheed_mailto (contact_widget, mailto, file_list);
+		get_sylpheed_mailto (p, mailto, file_list);
 		break;
 	case MAILER_THUNDERBIRD:
-		get_thunderbird_mailto (contact_widget, mailto, file_list);
+		get_thunderbird_mailto (p, mailto, file_list);
 		break;
 	case MAILER_EVO:
 	default:
-		get_evo_mailto (contact_widget, mailto, file_list);
+		get_evo_mailto (p, mailto, file_list);
 	}
 
-	cmd = g_strdup_printf (mail_cmd, mailto->str);
+	cmd = g_strdup_printf (p->mail_cmd, mailto->str);
 	g_string_free (mailto, TRUE);
 
-	g_message ("Mailer type: %d", type);
+	g_message ("Mailer type: %d", p->type);
 	g_message ("Command: %s", cmd);
 
 	g_spawn_command_line_async (cmd, NULL);
@@ -360,30 +429,24 @@ send_files (NstPlugin *plugin,
 	return TRUE;
 }
 
-static 
-gboolean destroy (NstPlugin *plugin){
-	g_free (mail_cmd);
-	mail_cmd = NULL;
-	g_free (name);
-	name = NULL;
-	g_free (email);
-	email = NULL;
-	return TRUE;
-}
+static void
+evolution_plugin_finalize (GObject *object)
+{
+	EvolutionPlugin *p;
+
+	p = EVOLUTION_PLUGIN (object);
 
-static 
-NstPluginInfo plugin_info = {
-	"emblem-mail",
-	"evolution",
-	N_("Email"),
-	NULL,
-	NAUTILUS_CAPS_NONE,
-	init,
-	get_contacts_widget,
-	NULL,
-	send_files,
-	destroy
-}; 
-
-NST_INIT_PLUGIN (plugin_info)
+	g_free (p->mail_cmd);
+	p->mail_cmd = NULL;
+
+	g_free (p->name);
+	p->name = NULL;
+
+	g_free (p->email);
+	p->email = NULL;
+
+	gtk_widget_destroy (p->entry);
+	p->entry = NULL;
+
+}
 
diff --git a/src/plugins/evolution/evolution.nst-plugin.in b/src/plugins/evolution/evolution.nst-plugin.in
new file mode 100644
index 0000000..bcd313f
--- /dev/null
+++ b/src/plugins/evolution/evolution.nst-plugin.in
@@ -0,0 +1,6 @@
+[Nst Plugin]
+Module=nstevolution
+IAge=1
+_Name=Email
+Authors=Bastien Nocera <hadess hadess net>
+Icon=emblem-mail
diff --git a/src/plugins/nautilus-burn/nautilus-burn.c b/src/plugins/nautilus-burn/nautilus-burn.c
index cdaa09e..adb9611 100644
--- a/src/plugins/nautilus-burn/nautilus-burn.c
+++ b/src/plugins/nautilus-burn/nautilus-burn.c
@@ -1,8 +1,6 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/* 
+/*
  * Copyright (C) 2008 Jader Henrique da Silva
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -108,7 +106,7 @@ GtkWidget* get_contacts_widget (NstPlugin *plugin)
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget),
 				    renderer,
 				    FALSE);
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), 
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget),
 					renderer,
 					"icon-name", COL_PIXBUF,
 					NULL);
@@ -116,7 +114,7 @@ GtkWidget* get_contacts_widget (NstPlugin *plugin)
 	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget),
 				    renderer,
 				    TRUE);
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), 
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget),
 					renderer,
 					"text", COL_LABEL,
 					NULL);
@@ -162,7 +160,7 @@ gboolean send_files (NstPlugin *plugin,
 	return TRUE;
 }
 
-static 
+static
 gboolean destroy (NstPlugin *plugin){
 
 	g_object_unref (burn);
@@ -171,7 +169,7 @@ gboolean destroy (NstPlugin *plugin){
 
 }
 
-static 
+static
 NstPluginInfo plugin_info = {
 	"brasero",
 	"nautilus-burn",
@@ -183,7 +181,7 @@ NstPluginInfo plugin_info = {
 	NULL,
 	send_files,
 	destroy
-}; 
+};
 
 NST_INIT_PLUGIN (plugin_info)
 
diff --git a/src/plugins/nautilus-sendto-plugin.c b/src/plugins/nautilus-sendto-plugin.c
new file mode 100644
index 0000000..fd586bd
--- /dev/null
+++ b/src/plugins/nautilus-sendto-plugin.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2010 Bastien Nocera
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * General Public License for more av.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301  USA.
+ *
+ * Author: Bastien Nocera <hadess hadess net>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "nautilus-sendto-plugin.h"
+
+G_DEFINE_INTERFACE(NautilusSendtoPlugin, nautilus_sendto_plugin, G_TYPE_OBJECT)
+
+static void
+nautilus_sendto_plugin_default_init (NautilusSendtoPluginInterface *iface)
+{
+}
+
+/**
+ * nautilus_sendto_plugin_get_widget:
+ * @plugin: a #NautilusSendtoPlugin instance
+ * @file_list: (element-type utf8): a #GList of strings representing the files to send.
+ * The file list should not be cached, and can be used to create a good archive name,
+ * if the plugin allows for compression, for example.
+ *
+ * Returns a #GtkWidget for the plugin in question.
+ *
+ * Return value: a #GtkWidget, or %NULL if the plugin does not implement
+ * the required interface.
+ */
+GtkWidget *
+nautilus_sendto_plugin_get_widget (NautilusSendtoPlugin  *plugin,
+				   GList                 *file_list)
+{
+	NautilusSendtoPluginInterface *iface;
+
+	g_return_val_if_fail (NAUTILUS_SENDTO_IS_PLUGIN (plugin), FALSE);
+
+	iface = NAUTILUS_SENDTO_PLUGIN_GET_IFACE (plugin);
+
+	if (G_LIKELY (iface->get_widget != NULL))
+		return iface->get_widget (plugin, file_list);
+
+	return NULL;
+}
+
+/**
+ * nautilus_sendto_plugin_supports_mime_types:
+ * @plugin: a #NautilusSendtoPlugin instance
+ * @mime_types: a list of mime-types for the file types to send.
+ *
+ * Returns a #gboolean.
+ *
+ * Return value: %FALSE if one or more of the mime_types cannot be sent through that plugin.
+ */
+gboolean
+nautilus_sendto_plugin_supports_mime_types (NautilusSendtoPlugin  *plugin,
+					    const char           **mime_types)
+{
+	NautilusSendtoPluginInterface *iface;
+
+	g_return_val_if_fail (NAUTILUS_SENDTO_IS_PLUGIN (plugin), FALSE);
+
+	iface = NAUTILUS_SENDTO_PLUGIN_GET_IFACE (plugin);
+
+	if (G_LIKELY (iface->supports_mime_types != NULL))
+		return iface->supports_mime_types (plugin, mime_types);
+
+	return FALSE;
+}
+
+/**
+ * nautilus_sendto_plugin_send_files:
+ * @plugin: a #NautilusSendtoPlugin instance
+ * @file_list: (element-type utf8): a #GList of strings representing the files to send
+ *
+ * Returns a #gboolean representing failure or success
+ *
+ * Return value: %FALSE on failure.
+ */
+gboolean
+nautilus_sendto_plugin_send_files (NautilusSendtoPlugin *plugin,
+				   GList                *file_list)
+{
+	NautilusSendtoPluginInterface *iface;
+
+	g_return_val_if_fail (NAUTILUS_SENDTO_IS_PLUGIN (plugin), FALSE);
+
+	iface = NAUTILUS_SENDTO_PLUGIN_GET_IFACE (plugin);
+
+	if (G_LIKELY (iface->send_files != NULL))
+		return iface->send_files (plugin, file_list);
+
+	return FALSE;
+}
diff --git a/src/plugins/nautilus-sendto-plugin.h b/src/plugins/nautilus-sendto-plugin.h
new file mode 100644
index 0000000..ec640f1
--- /dev/null
+++ b/src/plugins/nautilus-sendto-plugin.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 Bastien Nocera
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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
+ * General Public License for more av.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301  USA.
+ *
+ * Author: Bastien Nocera <hadess hadess net>
+ */
+
+#ifndef __NAUTILUS_SENDTO_PLUGIN_H__
+#define __NAUTILUS_SENDTO_PLUGIN_H__
+
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_SENDTO_TYPE_PLUGIN              (nautilus_sendto_plugin_get_type ())
+#define NAUTILUS_SENDTO_PLUGIN(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_SENDTO_TYPE_PLUGIN, NautilusSendtoPlugin))
+#define NAUTILUS_SENDTO_PLUGIN_IFACE(obj)        (G_TYPE_CHECK_CLASS_CAST ((obj), NAUTILUS_SENDTO_TYPE_PLUGIN, NautilusSendtoPluginInterface))
+#define NAUTILUS_SENDTO_IS_PLUGIN(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_SENDTO_TYPE_PLUGIN))
+#define NAUTILUS_SENDTO_PLUGIN_GET_IFACE(obj)    (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NAUTILUS_SENDTO_TYPE_PLUGIN, NautilusSendtoPluginInterface))
+
+typedef struct _NautilusSendtoPlugin           NautilusSendtoPlugin; /* dummy typedef */
+typedef struct _NautilusSendtoPluginInterface  NautilusSendtoPluginInterface;
+
+struct _NautilusSendtoPluginInterface
+{
+	GTypeInterface g_iface;
+
+	gboolean    (*supports_mime_types) (NautilusSendtoPlugin *plugin,
+					    const char          **mime_types);
+	gboolean    (*send_files)  (NautilusSendtoPlugin *plugin,
+				    GList                *file_list);
+	GtkWidget  *(*get_widget)  (NautilusSendtoPlugin *plugin,
+				    GList                *file_list);
+};
+
+GType       nautilus_sendto_plugin_get_type                (void);
+GtkWidget  *nautilus_sendto_plugin_get_widget (NautilusSendtoPlugin  *plugin,
+					       GList                 *file_list);
+gboolean    nautilus_sendto_plugin_supports_mime_types (NautilusSendtoPlugin *plugin,
+							const char          **mime_types);
+gboolean    nautilus_sendto_plugin_send_files (NautilusSendtoPlugin *plugin,
+					       GList                *file_list);
+
+#define NAUTILUS_PLUGIN_REGISTER(TYPE_NAME, TypeName, type_name)					\
+	GType type_name##_get_type (void) G_GNUC_CONST;							\
+	G_MODULE_EXPORT void  peas_register_types (PeasObjectModule *module);				\
+	static GtkWidget *type_name##_get_widget (NautilusSendtoPlugin *plugin, GList *file_list);	\
+	static gboolean type_name##_send_files (NautilusSendtoPlugin *plugin, GList *file_list);	\
+	static gboolean type_name##_supports_mime_types (NautilusSendtoPlugin *plugin, const char **mime_types); \
+	static void nautilus_sendto_plugin_iface_init (NautilusSendtoPluginInterface *iface);		\
+	static void type_name##_finalize (GObject *object);						\
+	G_DEFINE_DYNAMIC_TYPE_EXTENDED (TypeName,							\
+					type_name,							\
+					PEAS_TYPE_EXTENSION_BASE,					\
+					0,								\
+					G_IMPLEMENT_INTERFACE_DYNAMIC (NAUTILUS_SENDTO_TYPE_PLUGIN,	\
+								       nautilus_sendto_plugin_iface_init)) \
+	static void											\
+	nautilus_sendto_plugin_iface_init (NautilusSendtoPluginInterface *iface)			\
+	{												\
+		iface->get_widget = type_name##_get_widget;						\
+		iface->send_files = type_name##_send_files;						\
+		iface->supports_mime_types = type_name##_supports_mime_types;				\
+	}												\
+	static void											\
+	type_name##_class_init (TypeName##Class *klass)							\
+	{												\
+		GObjectClass *object_class = G_OBJECT_CLASS (klass);					\
+		object_class->finalize = type_name##_finalize;						\
+	}												\
+	static void											\
+	type_name##_class_finalize (TypeName##Class *klass)						\
+	{												\
+	}												\
+	G_MODULE_EXPORT void										\
+	peas_register_types (PeasObjectModule *module)							\
+	{												\
+		type_name##_register_type (G_TYPE_MODULE (module));					\
+		peas_object_module_register_extension_type (module,					\
+							    NAUTILUS_SENDTO_TYPE_PLUGIN,		\
+							    TYPE_NAME);					\
+	}
+
+G_END_DECLS
+
+#endif /* __NAUTILUS_SENDTO_PLUGIN_MANAGER_H__  */
diff --git a/src/plugins/nst-common.c b/src/plugins/nst-common.c
index 2d2f102..d0703f4 100644
--- a/src/plugins/nst-common.c
+++ b/src/plugins/nst-common.c
@@ -18,7 +18,11 @@
  * Author:  Maxim Ermilov <ermilov maxim gmail com>
  */
 
+#include "config.h"
+
 #include <gio/gio.h>
+#include <glib/gi18n-lib.h>
+#include "nst-common.h"
 
 static gboolean
 copy_fobject (GFile* source, GFile* dst)
@@ -96,3 +100,320 @@ copy_files_to (GList *file_list, GFile *dest)
 
 	return retval;
 }
+
+#define NAUTILUS_SENDTO_LAST_COMPRESS	"last-compress"
+
+struct NstPackWidgetPrivate {
+	GtkWidget *pack_combobox;
+	GtkWidget *pack_entry;
+	GtkWidget *pack_checkbutton;
+};
+
+G_DEFINE_TYPE (NstPackWidget, nst_pack_widget, GTK_TYPE_VBOX)
+#define NST_PACK_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NST_TYPE_PACK_WIDGET, NstPackWidgetPrivate))
+
+static void pack_entry_changed_cb (GObject *object, GParamSpec *spec, NstPackWidget *widget);
+static void toggle_pack_check (GtkWidget *toggle, NstPackWidget *widget);
+
+static char *
+get_filename_from_list (GList *file_list)
+{
+	GList *l;
+	GString *common_part = NULL;
+	gboolean matches = TRUE;
+	guint offset = 0;
+	const char *encoding;
+	gboolean use_utf8 = TRUE;
+
+	encoding = g_getenv ("G_FILENAME_ENCODING");
+
+	if (encoding != NULL && strcasecmp (encoding, "UTF-8") != 0)
+		use_utf8 = FALSE;
+
+	if (file_list == NULL)
+		return NULL;
+
+	common_part = g_string_new ("");
+
+	while (TRUE) {
+		gunichar cur_char = '\0';
+		for (l = file_list; l ; l = l->next) {
+			char *path = NULL, *name = NULL;
+			char *offset_name = NULL;
+
+			path = g_filename_from_uri ((char *) l->data, NULL, NULL);
+			if (!path)
+				break;
+
+			name = g_path_get_basename (path);
+
+			if (!use_utf8) {
+				char *tmp;
+
+				tmp = g_filename_to_utf8 (name, -1, NULL, NULL, NULL);
+				g_free (name);
+				name = tmp;
+			}
+
+			if (!name) {
+				g_free (path);
+				break;
+			}
+
+			if (offset >= g_utf8_strlen (name, -1)) {
+				g_free(name);
+				g_free(path);
+				matches = FALSE;
+				break;
+			}
+
+			offset_name = g_utf8_offset_to_pointer (name, offset);
+
+			if (offset_name == g_utf8_strrchr (name, -1, '.')) {
+				g_free (name);
+				g_free (path);
+				matches = FALSE;
+				break;
+			}
+			if (cur_char == '\0') {
+				cur_char = g_utf8_get_char (offset_name);
+			} else if (cur_char != g_utf8_get_char (offset_name)) {
+				g_free (name);
+				g_free (path);
+				matches = FALSE;
+				break;
+			}
+			g_free (name);
+			g_free (path);
+		}
+		if (matches == TRUE && cur_char != '\0') {
+			offset++;
+			common_part = g_string_append_unichar (common_part,
+					cur_char);
+		} else {
+			break;
+		}
+	}
+
+	if (g_utf8_strlen (common_part->str, -1) < 4) {
+		g_string_free (common_part, TRUE);
+		return NULL;
+	}
+
+	return g_string_free (common_part, FALSE);
+}
+
+static void
+nst_pack_widget_class_init (NstPackWidgetClass *klass)
+{
+	g_type_class_add_private (klass, sizeof (NstPackWidgetPrivate));
+}
+
+static void
+nst_pack_widget_init (NstPackWidget *self)
+{
+	GtkBuilder *builder;
+	GError *error = NULL;
+	GtkWidget *vbox;
+	NstPackWidgetPrivate *priv;
+	GSettings *settings;
+
+	self->priv = NST_PACK_WIDGET_GET_PRIVATE (self);
+	priv = self->priv;
+
+	builder = gtk_builder_new ();
+	//FIXME load from system
+	if (!gtk_builder_add_from_file (builder, "plugins/pack-entry.ui", &error)) {
+		g_warning ("Couldn't load builder file: %s", error->message);
+		g_error_free (error);
+	}
+
+	vbox = GTK_WIDGET (gtk_builder_get_object (builder, "vbox4"));
+	priv->pack_combobox = GTK_WIDGET (gtk_builder_get_object (builder, "pack_combobox"));
+	priv->pack_entry = GTK_WIDGET (gtk_builder_get_object (builder, "pack_entry"));
+	priv->pack_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder, "pack_checkbutton"));
+
+	gtk_entry_set_text (GTK_ENTRY (priv->pack_entry), _("Files"));
+
+	g_signal_connect (G_OBJECT (priv->pack_entry), "notify::text",
+			  G_CALLBACK (pack_entry_changed_cb), self);
+	g_signal_connect (G_OBJECT (priv->pack_checkbutton), "toggled",
+			  G_CALLBACK (toggle_pack_check), self);
+
+
+	settings = g_settings_new ("org.gnome.Nautilus.Sendto");
+	gtk_combo_box_set_active (GTK_COMBO_BOX (priv->pack_combobox),
+				  g_settings_get_int (settings,
+						      NAUTILUS_SENDTO_LAST_COMPRESS));
+	g_object_unref (settings);
+
+	gtk_container_add (GTK_CONTAINER (self), vbox);
+}
+
+void
+nst_pack_widget_set_from_names (NstPackWidget *widget,
+				GList         *file_list)
+{
+	NstPackWidgetPrivate *priv;
+	gboolean one_file;
+
+	priv = widget->priv;
+
+	if (file_list != NULL && file_list->next != NULL)
+		one_file = FALSE;
+	else if (file_list != NULL)
+		one_file = TRUE;
+
+	if (one_file) {
+		char *filepath = NULL, *filename = NULL;
+
+		filepath = g_filename_from_uri ((char *)file_list->data,
+				NULL, NULL);
+
+		if (filepath != NULL)
+			filename = g_path_get_basename (filepath);
+		if (filename != NULL && filename[0] != '\0')
+			gtk_entry_set_text (GTK_ENTRY (priv->pack_entry), filename);
+
+		g_free (filename);
+		g_free (filepath);
+	} else {
+		char *filename = get_filename_from_list (file_list);
+		if (filename != NULL && filename[0] != '\0') {
+			gtk_entry_set_text (GTK_ENTRY (priv->pack_entry),
+					filename);
+		}
+		g_free (filename);
+	}
+}
+
+char *
+nst_pack_widget_pack_files (NstPackWidget *widget,
+			    GList         *file_list)
+{
+	char *file_roller_cmd;
+	const char *filename;
+	GList *l;
+	GString *cmd, *tmp;
+	char *pack_type, *tmp_dir, *tmp_work_dir, *packed_file;
+	NstPackWidgetPrivate *priv;
+	GSettings *settings;
+
+	priv = widget->priv;
+	file_roller_cmd = g_find_program_in_path ("file-roller");
+	filename = gtk_entry_get_text (GTK_ENTRY (widget->priv->pack_entry));
+
+	g_assert (filename != NULL && *filename != '\0');
+
+	tmp_dir = g_strdup_printf ("%s/nautilus-sendto-%s",
+				   g_get_tmp_dir (), g_get_user_name ());
+	g_mkdir (tmp_dir, 0700);
+	tmp_work_dir = g_strdup_printf ("%s/nautilus-sendto-%s/%li",
+					g_get_tmp_dir (), g_get_user_name (),
+					time (NULL));
+	g_mkdir (tmp_work_dir, 0700);
+	g_free (tmp_dir);
+
+	switch (gtk_combo_box_get_active (GTK_COMBO_BOX (priv->pack_combobox)))
+	{
+	case 0:
+		pack_type = g_strdup (".zip");
+		break;
+	case 1:
+		pack_type = g_strdup (".tar.gz");
+		break;
+	case 2:
+		pack_type = g_strdup (".tar.bz2");
+		break;
+	default:
+		pack_type = NULL;
+		g_assert_not_reached ();
+	}
+
+	settings = g_settings_new ("org.gnome.Nautilus.Sendto");
+	g_settings_set_int (settings,
+			    NAUTILUS_SENDTO_LAST_COMPRESS,
+			    gtk_combo_box_get_active (GTK_COMBO_BOX (priv->pack_combobox)));
+	g_object_unref (settings);
+
+	cmd = g_string_new ("");
+	g_string_printf (cmd, "%s --add-to=\"%s/%s%s\"",
+			 file_roller_cmd, tmp_work_dir,
+			 filename,
+			 pack_type);
+
+	/* file-roller doesn't understand URIs */
+	for (l = file_list ; l; l=l->next){
+		char *file;
+
+		file = g_filename_from_uri (l->data, NULL, NULL);
+		g_string_append_printf (cmd," \"%s\"", file);
+		g_free (file);
+	}
+
+	g_spawn_command_line_sync (cmd->str, NULL, NULL, NULL, NULL);
+	g_string_free (cmd, TRUE);
+	tmp = g_string_new("");
+	g_string_printf (tmp,"%s/%s%s", tmp_work_dir,
+			 filename,
+			 pack_type);
+	g_free (tmp_work_dir);
+	packed_file = g_filename_to_uri (tmp->str, NULL, NULL);
+	g_string_free(tmp, TRUE);
+
+	return packed_file;
+}
+
+static void
+toggle_pack_check (GtkWidget *toggle, NstPackWidget *widget)
+{
+	GtkToggleButton *t = GTK_TOGGLE_BUTTON (toggle);
+	gboolean enabled, send_enabled;
+	NstPackWidgetPrivate *priv;
+
+	priv = widget->priv;
+	enabled = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (t));
+	gtk_widget_set_sensitive (priv->pack_combobox, enabled);
+	gtk_widget_set_sensitive (priv->pack_entry, enabled);
+
+	send_enabled = TRUE;
+
+	if (enabled) {
+		const char *filename;
+
+		filename = gtk_entry_get_text (GTK_ENTRY (priv->pack_entry));
+		if (filename == NULL || *filename == '\0')
+			send_enabled = FALSE;
+	}
+
+//FIXME changed property
+//	gtk_widget_set_sensitive (priv->send_button, send_enabled);
+}
+
+static void
+pack_entry_changed_cb (GObject *object, GParamSpec *spec, NstPackWidget *widget)
+{
+	gboolean send_enabled;
+	NstPackWidgetPrivate *priv;
+
+	priv = widget->priv;
+	send_enabled = TRUE;
+
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->pack_checkbutton))) {
+		const char *filename;
+
+		filename = gtk_entry_get_text(GTK_ENTRY(priv->pack_entry));
+		if (filename == NULL || *filename == '\0')
+			send_enabled = FALSE;
+	}
+
+//FIXME changed property
+//	gtk_widget_set_sensitive (ui->send_button, send_enabled);
+}
+
+GtkWidget *
+nst_pack_widget_new (void)
+{
+	return g_object_new (NST_TYPE_PACK_WIDGET, NULL);
+}
+
diff --git a/src/plugins/nst-common.h b/src/plugins/nst-common.h
index 5a5e1dd..9d890f7 100644
--- a/src/plugins/nst-common.h
+++ b/src/plugins/nst-common.h
@@ -1,5 +1,4 @@
 /*
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -16,8 +15,38 @@
  * Boston, MA 02110-1301  USA.
  *
  * Author:  Maxim Ermilov <ermilov maxim gmail com>
+ *          Bastien Nocera <hadess hadess net>
  */
 
 #include <gio/gio.h>
 
 gboolean copy_files_to (GList *file_list, GFile *dest);
+
+#include <gtk/gtk.h>
+
+#define NST_TYPE_PACK_WIDGET         (nst_pack_widget_get_type ())
+#define NST_PACK_WIDGET(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), NST_TYPE_PACK_WIDGET, NstPackWidget))
+#define NST_PACK_WIDGET_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), NST_TYPE_PACK_WIDGET, NstPackWidget))
+#define NST_IS_PACK_WIDGET(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), NST_TYPE_PACK_WIDGET))
+#define NST_IS_PACK_WIDGET_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), NST_TYPE_PACK_WIDGET))
+#define NST_PACK_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NST_TYPE_PACK_WIDGET, NstPackWidgetClass))
+
+typedef struct NstPackWidgetPrivate NstPackWidgetPrivate;
+
+typedef struct {
+	GtkVBox parent;
+	NstPackWidgetPrivate *priv;
+} NstPackWidget;
+
+typedef struct {
+	GtkVBoxClass parent;
+} NstPackWidgetClass;
+
+GType nst_pack_widget_get_type      (void);
+GtkWidget *nst_pack_widget_new      (void);
+
+char *nst_pack_widget_pack_files    (NstPackWidget *widget,
+				     GList         *file_list);
+void nst_pack_widget_set_from_names (NstPackWidget *widget,
+				     GList         *file_list);
+
diff --git a/src/plugins/removable-devices/Makefile.am b/src/plugins/removable-devices/Makefile.am
index 8a36e2d..ee71da4 100644
--- a/src/plugins/removable-devices/Makefile.am
+++ b/src/plugins/removable-devices/Makefile.am
@@ -1,5 +1,9 @@
 plugindir = $(libdir)/nautilus-sendto/plugins
 
+plugin_in_files = removable-devices.nst-plugin.in
+%.nst-plugin: %.nst-plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+plugin_DATA = removable-devices.nst-plugin
+
 INCLUDES =                                      \
         -DDATADIR=\"$(datadir)\"                \
         -DICONDIR=\"$(icondir)\"                \
@@ -15,5 +19,6 @@ plugin_LTLIBRARIES = libnstremovable_devices.la
 
 libnstremovable_devices_la_SOURCES = removable-devices.c
 libnstremovable_devices_la_LDFLAGS = -module -avoid-version
-libnstremovable_devices_la_LIBADD = $(GIO_LIBS) $(NAUTILUS_SENDTO_LIBS) $(builddir)/../libnstcommon.la
+libnstremovable_devices_la_LIBADD = $(GIO_LIBS) $(NAUTILUS_SENDTO_LIBS) $(builddir)/../libnstcommon.la $(builddir)/../libnautilussendto-1.0.la
 
+EXTRA_DIST = $(plugin_in_files)
diff --git a/src/plugins/removable-devices/removable-devices.c b/src/plugins/removable-devices/removable-devices.c
index 68022c4..8a81f4a 100644
--- a/src/plugins/removable-devices/removable-devices.c
+++ b/src/plugins/removable-devices/removable-devices.c
@@ -1,5 +1,4 @@
 /*
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -26,6 +25,29 @@
 #include "nst-common.h"
 #include "nautilus-sendto-plugin.h"
 
+#define REMOVABLE_TYPE_DEVICES_PLUGIN         (removable_devices_plugin_get_type ())
+#define REMOVABLE_DEVICES_PLUGIN(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), REMOVABLE_TYPE_DEVICES_PLUGIN, RemovableDevicesPlugin))
+#define REMOVABLE_DEVICES_PLUGIN_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), REMOVABLE_TYPE_DEVICES_PLUGIN, RemovableDevicesPlugin))
+#define REMOVABLE_IS_DEVICES_PLUGIN(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), REMOVABLE_TYPE_DEVICES_PLUGIN))
+#define REMOVABLE_IS_DEVICES_PLUGIN_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), REMOVABLE_TYPE_DEVICES_PLUGIN))
+#define REMOVABLE_DEVICES_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), REMOVABLE_TYPE_DEVICES_PLUGIN, RemovableDevicesPluginClass))
+
+typedef struct _RemovableDevicesPlugin       RemovableDevicesPlugin;
+typedef struct _RemovableDevicesPluginClass  RemovableDevicesPluginClass;
+
+struct _RemovableDevicesPlugin {
+	PeasExtensionBase parent_instance;
+
+	GVolumeMonitor *vol_monitor;
+	GtkWidget *cb;
+};
+
+struct _RemovableDevicesPluginClass {
+	PeasExtensionBaseClass parent_class;
+};
+
+NAUTILUS_PLUGIN_REGISTER(REMOVABLE_TYPE_DEVICES_PLUGIN, RemovableDevicesPlugin, removable_devices_plugin)
+
 enum {
 	NAME_COL,
 	ICON_COL,
@@ -33,19 +55,16 @@ enum {
 	NUM_COLS,
 };
 
-GVolumeMonitor* vol_monitor = NULL;
-GtkWidget *cb;
-
 static void
-cb_mount_removed (GVolumeMonitor *volume_monitor,
-		  GMount         *mount,
-		  NstPlugin      *plugin)
+cb_mount_removed (GVolumeMonitor         *volume_monitor,
+		  GMount                 *mount,
+		  RemovableDevicesPlugin *p)
 {
 	GtkTreeIter iter;
 	GtkListStore *store;
 	gboolean b, found;
 
-	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb)));
+	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (p->cb)));
 	b = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
 	found = FALSE;
 
@@ -65,28 +84,28 @@ cb_mount_removed (GVolumeMonitor *volume_monitor,
 	/* If a mount was removed */
 	if (found != FALSE) {
 		/* And it was the selected one */
-		if (gtk_combo_box_get_active (GTK_COMBO_BOX (cb)) == -1) {
+		if (gtk_combo_box_get_active (GTK_COMBO_BOX (p->cb)) == -1) {
 			/* Select the first item in the list */
-			gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+			gtk_combo_box_set_active (GTK_COMBO_BOX (p->cb), 0);
 		}
 	}
 }
 
 static void
-cb_mount_changed (GVolumeMonitor *volume_monitor,
-		  GMount         *mount,
-		  NstPlugin      *plugin)
+cb_mount_changed (GVolumeMonitor         *volume_monitor,
+		  GMount                 *mount,
+		  RemovableDevicesPlugin *p)
 {
 	GtkTreeIter iter;
 	gboolean b;
 	GtkListStore *store;
 
 	if (g_mount_is_shadowed (mount) != FALSE) {
-		cb_mount_removed (volume_monitor, mount, plugin);
+		cb_mount_removed (volume_monitor, mount, p);
 		return;
 	}
 
-	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb)));
+	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (p->cb)));
 	b = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
 
 	while (b) {
@@ -111,9 +130,9 @@ cb_mount_changed (GVolumeMonitor *volume_monitor,
 }
 
 static void
-cb_mount_added (GVolumeMonitor *volume_monitor,
-		GMount         *mount,
-		NstPlugin      *plugin)
+cb_mount_added (GVolumeMonitor         *volume_monitor,
+		GMount                 *mount,
+		RemovableDevicesPlugin *p)
 {
 	char *name;
 	GtkTreeIter iter;
@@ -124,7 +143,7 @@ cb_mount_added (GVolumeMonitor *volume_monitor,
 		return;
 
 	name = g_mount_get_name (mount);
-	model = gtk_combo_box_get_model (GTK_COMBO_BOX (cb));
+	model = gtk_combo_box_get_model (GTK_COMBO_BOX (p->cb));
 
 	select_added = gtk_tree_model_iter_n_children (model, NULL) == 0;
 
@@ -138,33 +157,54 @@ cb_mount_added (GVolumeMonitor *volume_monitor,
 	g_free (name);
 
 	if (select_added != FALSE)
-		gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+		gtk_combo_box_set_active (GTK_COMBO_BOX (p->cb), 0);
 
 }
 
 static gboolean
-init (NstPlugin *plugin)
+removable_devices_plugin_send_files (NautilusSendtoPlugin *plugin,
+				     GList                *file_list)
 {
-	g_print ("Init removable-devices plugin\n");
+	RemovableDevicesPlugin *p = REMOVABLE_DEVICES_PLUGIN (plugin);
+	GtkListStore *store;
+	GtkTreeIter iter;
+	GMount *dest_mount;
+	GFile *mount_root;
 
-	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
-	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (p->cb), &iter) == FALSE)
+		return TRUE;
+
+	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (p->cb)));
+	gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &dest_mount, -1);
+	mount_root = g_mount_get_root (dest_mount);
+
+	copy_files_to (file_list, mount_root);
 
-	vol_monitor = g_volume_monitor_get ();
-	cb = gtk_combo_box_new ();
+	g_object_unref (mount_root);
 
 	return TRUE;
 }
 
-static GtkWidget*
-get_contacts_widget (NstPlugin *plugin)
+static gboolean
+removable_devices_plugin_supports_mime_types (NautilusSendtoPlugin *plugin,
+					      const char          **mime_types)
+{
+	/* All the mime-types are supported */
+	return TRUE;
+}
+
+static GtkWidget *
+removable_devices_plugin_get_widget (NautilusSendtoPlugin *plugin,
+				     GList                *file_list)
 {
+	RemovableDevicesPlugin *p = REMOVABLE_DEVICES_PLUGIN (plugin);
 	GtkListStore *store;
 	GList *l, *mounts;
 	GtkTreeIter iter;
+	GtkWidget *box;
 	GtkCellRenderer *text_renderer, *icon_renderer;
 
-	mounts = g_volume_monitor_get_mounts (vol_monitor);
+	mounts = g_volume_monitor_get_mounts (p->vol_monitor);
 
 	store = gtk_list_store_new (NUM_COLS, G_TYPE_STRING, G_TYPE_ICON, G_TYPE_OBJECT);
 
@@ -190,70 +230,54 @@ get_contacts_widget (NstPlugin *plugin)
 	}
 	g_list_free (mounts);
 
-	gtk_cell_layout_clear (GTK_CELL_LAYOUT (cb));
-	gtk_combo_box_set_model (GTK_COMBO_BOX (cb), GTK_TREE_MODEL (store));
+	gtk_cell_layout_clear (GTK_CELL_LAYOUT (p->cb));
+	gtk_combo_box_set_model (GTK_COMBO_BOX (p->cb), GTK_TREE_MODEL (store));
 
 	text_renderer = gtk_cell_renderer_text_new ();
 	icon_renderer = gtk_cell_renderer_pixbuf_new ();
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), icon_renderer, FALSE);
-	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (cb), text_renderer, TRUE);
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (p->cb), icon_renderer, FALSE);
+	gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (p->cb), text_renderer, TRUE);
 
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), text_renderer, "text", 0,  NULL);
-	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (cb), icon_renderer, "gicon", 1,  NULL);
-	gtk_combo_box_set_active (GTK_COMBO_BOX (cb), 0);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (p->cb), text_renderer, "text", 0,  NULL);
+	gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (p->cb), icon_renderer, "gicon", 1,  NULL);
+	gtk_combo_box_set_active (GTK_COMBO_BOX (p->cb), 0);
 
-	g_signal_connect (G_OBJECT (vol_monitor), "mount-removed", G_CALLBACK (cb_mount_removed), plugin);
-	g_signal_connect (G_OBJECT (vol_monitor), "mount-added", G_CALLBACK (cb_mount_added), plugin);
-	g_signal_connect (G_OBJECT (vol_monitor), "mount-changed", G_CALLBACK (cb_mount_changed), plugin);
+	g_signal_connect (G_OBJECT (p->vol_monitor), "mount-removed", G_CALLBACK (cb_mount_removed), plugin);
+	g_signal_connect (G_OBJECT (p->vol_monitor), "mount-added", G_CALLBACK (cb_mount_added), plugin);
+	g_signal_connect (G_OBJECT (p->vol_monitor), "mount-changed", G_CALLBACK (cb_mount_changed), plugin);
 
-	return cb;
+	box = gtk_vbox_new (FALSE, 8);
+	gtk_box_pack_start (GTK_BOX (box), p->cb, TRUE, FALSE, 0);
+	gtk_widget_show_all (box);
+
+	return box;
 }
 
-static gboolean
-send_files (NstPlugin *plugin, GtkWidget *contact_widget,
-	    GList *file_list)
+static void
+removable_devices_plugin_init (RemovableDevicesPlugin *p)
 {
-	GtkListStore *store;
-	GtkTreeIter iter;
-	GMount *dest_mount;
-	GFile *mount_root;
-
-	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (contact_widget), &iter) == FALSE)
-		return TRUE;
-
-	store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (cb)));
-	gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, MOUNT_COL, &dest_mount, -1);
-	mount_root = g_mount_get_root (dest_mount);
-
-	copy_files_to (file_list, mount_root);
-
-	g_object_unref (mount_root);
+	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
-	return TRUE;
+	p->vol_monitor = g_volume_monitor_get ();
+	p->cb = gtk_combo_box_new ();
 }
 
-static gboolean
-destroy (NstPlugin *plugin)
+static void
+removable_devices_plugin_finalize (GObject *object)
 {
-	gtk_widget_destroy (cb);
+	RemovableDevicesPlugin *p = REMOVABLE_DEVICES_PLUGIN (object);
 
-	g_object_unref (vol_monitor);
-	return TRUE;
-}
+	if (p->cb != NULL) {
+		gtk_widget_destroy (p->cb);
+		p->cb = NULL;
+	}
 
-static
-NstPluginInfo plugin_info = {
-	"folder-remote",
-	"folder-remote",
-	N_("Removable disks and shares"),
-	NULL,
-	NAUTILUS_CAPS_SEND_DIRECTORIES,
-	init,
-	get_contacts_widget,
-	NULL,
-	send_files,
-	destroy
-};
+	if (p->vol_monitor != NULL) {
+		g_object_unref (p->vol_monitor);
+		p->vol_monitor = NULL;
+	}
 
-NST_INIT_PLUGIN (plugin_info)
+	G_OBJECT_CLASS (removable_devices_plugin_parent_class)->finalize (object);
+}
 
diff --git a/src/plugins/removable-devices/removable-devices.nst-plugin.in b/src/plugins/removable-devices/removable-devices.nst-plugin.in
new file mode 100644
index 0000000..801b369
--- /dev/null
+++ b/src/plugins/removable-devices/removable-devices.nst-plugin.in
@@ -0,0 +1,6 @@
+[Nst Plugin]
+Module=nstremovable_devices
+IAge=1
+_Name=Removable disks and shares
+Authors=Maxim Ermilov <ermilov maxim gmail com>, Bastien Nocera <hadess hadess net>
+Icon=folder-remote



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]