[nautilus-actions: 15/30] Define NagpGConfProvider as an IO provider



commit f413c5c03a60c36c214fa53e2c12e785dc0657d8
Author: Pierre Wieser <pwieser trychlos org>
Date:   Thu Nov 19 23:04:13 2009 +0100

    Define NagpGConfProvider as an IO provider

 ChangeLog                                          |   41 ++
 TODO                                               |    2 +
 configure.ac                                       |    1 +
 m4/na-log-domains.m4                               |    3 +
 nautilus-actions/Makefile.am                       |    1 +
 nautilus-actions/api/na-api.h                      |    3 +-
 nautilus-actions/io-provider-gconf/Makefile.am     |   57 +++
 .../nagp-gconf-provider.c}                         |  414 ++++++++++++--------
 .../io-provider-gconf/nagp-gconf-provider.h        |   80 ++++
 .../nagp-keys.h}                                   |   36 +-
 nautilus-actions/io-provider-gconf/nagp-module.c   |  160 ++++++++
 nautilus-actions/nact/nact-xml-reader.c            |    3 +-
 nautilus-actions/plugin/nautilus-actions.h         |    2 +-
 nautilus-actions/plugin/nautilus-module.c          |    2 +
 nautilus-actions/runtime/Makefile.am               |    3 -
 nautilus-actions/runtime/na-gconf-provider.h       |   81 ----
 nautilus-actions/runtime/na-gconf-utils.c          |  104 -----
 nautilus-actions/runtime/na-gconf-utils.h          |    5 -
 nautilus-actions/runtime/na-module.c               |  330 +++++++++-------
 nautilus-actions/runtime/na-module.h               |   11 +-
 nautilus-actions/runtime/na-pivot.c                |   35 +--
 nautilus-actions/runtime/na-xml-writer.c           |    3 +-
 nautilus-actions/utils/nautilus-actions-new.c      |    8 +-
 23 files changed, 834 insertions(+), 551 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 291c602..5facc1b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2009-11-19 Pierre Wieser <pwieser trychlos org>
+
+	Create GConf IO Provider as a plugin.
+
+	* nautilus-actions/runtime/na-gconf-provider-keys.h:
+	* nautilus-actions/runtime/na-gconf-provider.c:
+	* nautilus-actions/runtime/na-gconf-provider.h:
+	Moved to io-provider-gconf/, and thus removed from runtime/.
+
+	* configure.ac:
+	* nautilus-actions/Makefile.am:
+	Maage io-provider-gconf/ new directory.
+
+	* m4/na-log-domains.m4:
+	Define new NA_LOGDOMAIN_IO_PROVIDER_GCONF log domain.
+
+	* nautilus-actions/api/na-api.c:
+	* nautilus-actions/api/na-api.h (na_api_module_init):
+	Now returns a boolean.
+
+	* nautilus-actions/plugin/nautilus-module.c:
+	Set module name.
+
+	* nautilus-actions/runtime/na-gconf-utils.c:
+	* nautilus-actions/runtime/na-gconf-utils.h
+	(na_gconf_utils_get_subdirs, na_gconf_utils_free_subdirs,
+	na_gconf_utils_have_entry:): Move functions to NagpIOProvider class.
+
+	* nautilus-actions/runtime/na-module.c:
+	Fix dynamic loading of the modules.
+
+	* nautilus-actions/runtime/na-gconf-utils.c:
+	* nautilus-actions/runtime/na-gconf-utils.h
+	(na_gconf_utils_have_subdir): Removed function.
+
+	* nautilus-actions/nact/nact-xml-reader.c:
+	* nautilus-actions/runtime/Makefile.am:
+	* nautilus-actions/runtime/na-pivot.c:
+	* nautilus-actions/runtime/na-xml-writer.c:
+	Updated accordingly.
+
 2009-11-18 Pierre Wieser <pwieser trychlos org>
 
 	Move runtime/na-gconf-monitor.{c,h} to api/.
diff --git a/TODO b/TODO
index 4eacefb..cc622de 100644
--- a/TODO
+++ b/TODO
@@ -80,3 +80,5 @@
 - export: add a overwrite page: what to do if file already exists ?
 
 - na_object_id_get_topmost_parent: should it return a NAObjectItem ?
+
+- nautilus-actions-new: write to GConf
diff --git a/configure.ac b/configure.ac
index e57b119..8d4b890 100644
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,7 @@ AC_CONFIG_FILES([
 	icons/scalable/Makefile
 	nautilus-actions/Makefile
 	nautilus-actions/api/Makefile
+	nautilus-actions/io-provider-gconf/Makefile
 	nautilus-actions/nact/Makefile
 	nautilus-actions/plugin/Makefile
 	nautilus-actions/private/Makefile
diff --git a/m4/na-log-domains.m4 b/m4/na-log-domains.m4
index 29559d4..517e333 100644
--- a/m4/na-log-domains.m4
+++ b/m4/na-log-domains.m4
@@ -8,6 +8,9 @@ AC_DEFUN([NA_LOG_DOMAINS],[
 	AC_SUBST([NA_LOGDOMAIN_API],[NA-api])
 	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_API],["NA-api"],[Log domain of API library])
 
+	AC_SUBST([NA_LOGDOMAIN_IO_PROVIDER_GCONF],[NA-io-provider-gconf])
+	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_IO_PROVIDER_GCONF],["NA-io-provider-gconf"],[Log domain of GConf IO Provider])
+
 	AC_SUBST([NA_LOGDOMAIN_NACT],[NA-nact])
 	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_NACT],["NA-nact"],[Log domain of NACT user interface])
 
diff --git a/nautilus-actions/Makefile.am b/nautilus-actions/Makefile.am
index d503dcd..a1969d1 100644
--- a/nautilus-actions/Makefile.am
+++ b/nautilus-actions/Makefile.am
@@ -29,6 +29,7 @@
 SUBDIRS = \
 	api							\
 	private						\
+	io-provider-gconf			\
 	runtime						\
 	nact						\
 	plugin						\
diff --git a/nautilus-actions/api/na-api.h b/nautilus-actions/api/na-api.h
index 5c6fb84..e332171 100644
--- a/nautilus-actions/api/na-api.h
+++ b/nautilus-actions/api/na-api.h
@@ -54,8 +54,9 @@ G_BEGIN_DECLS
  *
  * The dynamically loaded library may benefit of being triggered by
  * initializing itself, registering its internal GTypes, etc.
+ * It should at least register module GTypes it provides.
  */
-void         na_api_module_init      ( GTypeModule *module );
+gboolean     na_api_module_init      ( GTypeModule *module );
 
 /**
  * na_api_module_list_types:
diff --git a/nautilus-actions/io-provider-gconf/Makefile.am b/nautilus-actions/io-provider-gconf/Makefile.am
new file mode 100644
index 0000000..2bbc48b
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/Makefile.am
@@ -0,0 +1,57 @@
+# Nautilus Actions
+# A Nautilus extension which offers configurable context menu actions.
+#
+# Copyright (C) 2005 The GNOME Foundation
+# Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+# Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+#
+# 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 details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this Library; see the file COPYING.  If not,
+# write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA 02111-1307, USA.
+#
+# Authors:
+#   Frederic Ruaudel <grumz grumz net>
+#   Rodrigo Moya <rodrigo gnome-db org>
+#   Pierre Wieser <pwieser trychlos org>
+#   ... and many others (see AUTHORS)
+
+pluginsdir = $(pkglibdir)
+
+plugins_LTLIBRARIES=libna-io-provider-gconf.la
+
+AM_CPPFLAGS += \
+	-I $(top_srcdir)											\
+	$(NAUTILUS_ACTIONS_CFLAGS)									\
+	-DG_LOG_DOMAIN=\"${NA_LOGDOMAIN_IO_PROVIDER_GCONF}\"		\
+	$(NULL)
+
+libna_io_provider_gconf_la_SOURCES = \
+	nagp-gconf-provider.c										\
+	nagp-gconf-provider.h										\
+	nagp-keys.h													\
+	nagp-module.c												\
+	$(NULL)
+
+libna_io_provider_gconf_la_LIBADD = \
+	-L$(top_builddir)/nautilus-actions/api		-lna-api		\
+	-L$(top_builddir)/nautilus-actions/private	-lna-private	\
+	-L$(top_builddir)/nautilus-actions/runtime	-lna-runtime	\
+	$(NULL)
+
+VERSION_INFO = 1:0:0
+libna_io_provider_gconf_la_LDFLAGS = \
+	-module 													\
+	-no-undefined												\
+	-version-number $(VERSION_INFO)								\
+	$(NULL)
diff --git a/nautilus-actions/runtime/na-gconf-provider.c b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
similarity index 71%
rename from nautilus-actions/runtime/na-gconf-provider.c
rename to nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
index d9369de..547195b 100644
--- a/nautilus-actions/runtime/na-gconf-provider.c
+++ b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
@@ -34,96 +34,98 @@
 
 #include <string.h>
 
-#include <api/na-object-api.h>
-#include <api/na-gconf-monitor.h>
+#include <nautilus-actions/api/na-iio-provider.h>
+#include <nautilus-actions/api/na-object-api.h>
+#include <nautilus-actions/api/na-gconf-monitor.h>
 
-#include "na-gconf-provider.h"
-#include "na-gconf-provider-keys.h"
-#include "na-gconf-utils.h"
-#include "na-utils.h"
+/* only possible because we are an internal plugin */
+#include <runtime/na-gconf-utils.h>
+#include <runtime/na-utils.h>
+
+#include "nagp-gconf-provider.h"
+#include "nagp-keys.h"
 
 /* private class data
  */
-struct NAGConfProviderClassPrivate {
+struct NagpGConfProviderClassPrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
 /* private instance data
  */
-struct NAGConfProviderPrivate {
+struct NagpGConfProviderPrivate {
 	gboolean     dispose_has_run;
 	GConfClient *gconf;
-	NAPivot     *pivot;
 	GList       *monitors;
 };
 
+static GType         st_module_type = 0;
 static GObjectClass *st_parent_class = NULL;
 
-static GType          register_type( void );
-static void           class_init( NAGConfProviderClass *klass );
+static void           class_init( NagpGConfProviderClass *klass );
 static void           iio_provider_iface_init( NAIIOProviderInterface *iface );
 static void           instance_init( GTypeInstance *instance, gpointer klass );
 static void           instance_dispose( GObject *object );
 static void           instance_finalize( GObject *object );
 
-static void           install_monitors( NAGConfProvider *provider );
-static void           config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NAGConfProvider *provider );
+static GList         *install_monitors( NagpGConfProvider *provider );
+static void           config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NagpGConfProvider *provider );
+#if 0
 static NAPivotNotify *entry_to_notify( const GConfEntry *entry );
+#endif
 
 static GList         *iio_provider_read_items( const NAIIOProvider *provider, GSList **messages );
-static NAObjectItem  *read_item( NAGConfProvider *provider, const gchar *path );
-static void           read_item_action( NAGConfProvider *provider, const gchar *path, NAObjectAction *action );
-static void           read_item_action_properties( NAGConfProvider *provider, GSList *entries, NAObjectAction *action );
-static void           read_item_action_properties_v1( NAGConfProvider *gconf, GSList *entries, NAObjectAction *action );
-static void           read_item_action_profile( NAGConfProvider *provider, NAObjectAction *action, const gchar *path );
-static void           read_item_action_profile_properties( NAGConfProvider *provider, GSList *entries, NAObjectProfile *profile );
-static void           read_item_menu( NAGConfProvider *provider, const gchar *path, NAObjectMenu *menu );
-static void           read_item_menu_properties( NAGConfProvider *provider, GSList *entries, NAObjectMenu *menu );
-static void           read_object_item_properties( NAGConfProvider *provider, GSList *entries, NAObjectItem *item );
+static NAObjectItem  *read_item( NagpGConfProvider *provider, const gchar *path );
+static void           read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction *action );
+static void           read_item_action_properties( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action );
+static void           read_item_action_properties_v1( NagpGConfProvider *gconf, GSList *entries, NAObjectAction *action );
+static void           read_item_action_profile( NagpGConfProvider *provider, NAObjectAction *action, const gchar *path );
+static void           read_item_action_profile_properties( NagpGConfProvider *provider, GSList *entries, NAObjectProfile *profile );
+static void           read_item_menu( NagpGConfProvider *provider, const gchar *path, NAObjectMenu *menu );
+static void           read_item_menu_properties( NagpGConfProvider *provider, GSList *entries, NAObjectMenu *menu );
+static void           read_object_item_properties( NagpGConfProvider *provider, GSList *entries, NAObjectItem *item );
 
 static gboolean       iio_provider_is_willing_to_write( const NAIIOProvider *provider );
 
 static gboolean       iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item );
 
-static guint          iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages );
-static gboolean       write_item_action( NAGConfProvider *gconf, const NAObjectAction *action, GSList **messages );
-static gboolean       write_item_menu( NAGConfProvider *gconf, const NAObjectMenu *menu, GSList **messages );
-static gboolean       write_object_item( NAGConfProvider *gconf, const NAObjectItem *item, GSList **messages );
+static guint          iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
+static gboolean       write_item_action( NagpGConfProvider *gconf, const NAObjectAction *action, GSList **message );
+static gboolean       write_item_menu( NagpGConfProvider *gconf, const NAObjectMenu *menu, GSList **message );
+static gboolean       write_object_item( NagpGConfProvider *gconf, const NAObjectItem *item, GSList **message );
+
+static guint          iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
 
-static guint          iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages );
+static gboolean       key_is_writable( NagpGConfProvider *gconf, const gchar *path );
 
-static gboolean       key_is_writable( NAGConfProvider *gconf, const gchar *path );
+static gboolean       write_str( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **message );
+static gboolean       write_bool( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **message );
+static gboolean       write_list( NagpGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **message );
 
-static gboolean       write_str( NAGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **messages );
-static gboolean       write_bool( NAGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **messages );
-static gboolean       write_list( NAGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **messages );
+static GSList  *na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path );
+static void     na_gconf_utils_free_subdirs( GSList *subdirs );
+/*static gboolean na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path );*/
+static gboolean na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry );
 
 GType
-na_gconf_provider_get_type( void )
+nagp_gconf_provider_get_type( void )
 {
-	static GType object_type = 0;
-
-	if( !object_type ){
-		object_type = register_type();
-	}
-
-	return( object_type );
+	return( st_module_type );
 }
 
-static GType
-register_type( void )
+void
+nagp_gconf_provider_register_type( GTypeModule *module )
 {
-	static const gchar *thisfn = "na_gconf_provider_register_type";
-	GType type;
+	static const gchar *thisfn = "nagp_gconf_provider_register_type";
 
 	static GTypeInfo info = {
-		sizeof( NAGConfProviderClass ),
+		sizeof( NagpGConfProviderClass ),
 		NULL,
 		NULL,
 		( GClassInitFunc ) class_init,
 		NULL,
 		NULL,
-		sizeof( NAGConfProvider ),
+		sizeof( NagpGConfProvider ),
 		0,
 		( GInstanceInitFunc ) instance_init
 	};
@@ -136,17 +138,15 @@ register_type( void )
 
 	g_debug( "%s", thisfn );
 
-	type = g_type_register_static( G_TYPE_OBJECT, "NAGConfProvider", &info, 0 );
-
-	g_type_add_interface_static( type, NA_IIO_PROVIDER_TYPE, &iio_provider_iface_info );
+	st_module_type = g_type_module_register_type( module, G_TYPE_OBJECT, "NagpGConfProvider", &info, 0 );
 
-	return( type );
+	g_type_module_add_interface( module, st_module_type, NA_IIO_PROVIDER_TYPE, &iio_provider_iface_info );
 }
 
 static void
-class_init( NAGConfProviderClass *klass )
+class_init( NagpGConfProviderClass *klass )
 {
-	static const gchar *thisfn = "na_gconf_provider_class_init";
+	static const gchar *thisfn = "nagp_gconf_provider_class_init";
 	GObjectClass *object_class;
 
 	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -157,13 +157,13 @@ class_init( NAGConfProviderClass *klass )
 	object_class->dispose = instance_dispose;
 	object_class->finalize = instance_finalize;
 
-	klass->private = g_new0( NAGConfProviderClassPrivate, 1 );
+	klass->private = g_new0( NagpGConfProviderClassPrivate, 1 );
 }
 
 static void
 iio_provider_iface_init( NAIIOProviderInterface *iface )
 {
-	static const gchar *thisfn = "na_gconf_provider_iio_provider_iface_init";
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_iface_init";
 
 	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
 
@@ -177,30 +177,29 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
 static void
 instance_init( GTypeInstance *instance, gpointer klass )
 {
-	static const gchar *thisfn = "na_gconf_provider_instance_init";
-	NAGConfProvider *self;
+	static const gchar *thisfn = "nagp_gconf_provider_instance_init";
+	NagpGConfProvider *self;
 
 	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
-	g_return_if_fail( NA_IS_GCONF_PROVIDER( instance ));
-	self = NA_GCONF_PROVIDER( instance );
+	g_return_if_fail( NAGP_IS_GCONF_PROVIDER( instance ));
+	self = NAGP_GCONF_PROVIDER( instance );
 
-	self->private = g_new0( NAGConfProviderPrivate, 1 );
+	self->private = g_new0( NagpGConfProviderPrivate, 1 );
 
 	self->private->dispose_has_run = FALSE;
-	self->private->pivot = NULL;
-	self->private->gconf = NULL;
-	self->private->monitors = NULL;
+	self->private->gconf = gconf_client_get_default();
+	self->private->monitors = install_monitors( self );
 }
 
 static void
 instance_dispose( GObject *object )
 {
-	static const gchar *thisfn = "na_gconf_provider_instance_dispose";
-	NAGConfProvider *self;
+	static const gchar *thisfn = "nagp_gconf_provider_instance_dispose";
+	NagpGConfProvider *self;
 
 	g_debug( "%s: object=%p", thisfn, ( void * ) object );
-	g_return_if_fail( NA_IS_GCONF_PROVIDER( object ));
-	self = NA_GCONF_PROVIDER( object );
+	g_return_if_fail( NAGP_IS_GCONF_PROVIDER( object ));
+	self = NAGP_GCONF_PROVIDER( object );
 
 	if( !self->private->dispose_has_run ){
 
@@ -222,10 +221,10 @@ instance_dispose( GObject *object )
 static void
 instance_finalize( GObject *object )
 {
-	NAGConfProvider *self;
+	NagpGConfProvider *self;
 
-	g_assert( NA_IS_GCONF_PROVIDER( object ));
-	self = NA_GCONF_PROVIDER( object );
+	g_assert( NAGP_IS_GCONF_PROVIDER( object ));
+	self = NAGP_GCONF_PROVIDER( object );
 
 	g_free( self->private );
 
@@ -235,45 +234,14 @@ instance_finalize( GObject *object )
 	}
 }
 
-/**
- * na_gconf_provider_new:
- * @handler: the #NAPivot which is to be notified when an
- * item is added, modified or removed in underlying GConf system.
- *
- * Allocates a new #NAGConfProvider object.
- *
- * The specified #NAPivot object will receive a
- * "notify-consumer-of-action-change" message for each detected
- * modification, with a pointer to a newly allocated #NAPivotNotify
- * structure describing the change.
- */
-NAGConfProvider *
-na_gconf_provider_new( NAPivot *handler )
-{
-	NAGConfProvider *provider;
-
-	g_return_val_if_fail( NA_IS_PIVOT( handler ), NULL );
-
-	provider = g_object_new( NA_GCONF_PROVIDER_TYPE, NULL );
-
-	provider->private->gconf = gconf_client_get_default();
-
-	if( handler ){
-		provider->private->pivot = handler;
-		install_monitors( provider );
-	}
-
-	return( provider );
-}
-
-static void
-install_monitors( NAGConfProvider *provider )
+static GList *
+install_monitors( NagpGConfProvider *provider )
 {
 	GList *list = NULL;
 
-	g_return_if_fail( NA_IS_GCONF_PROVIDER( provider ));
-	g_return_if_fail( NA_IS_IIO_PROVIDER( provider ));
-	g_return_if_fail( !provider->private->dispose_has_run );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
+	g_return_val_if_fail( !provider->private->dispose_has_run, NULL );
 
 	/* monitor the configurations/ directory which contains all menus,
 	 * actions and profiles definitions
@@ -284,7 +252,7 @@ install_monitors( NAGConfProvider *provider )
 					( GConfClientNotifyFunc ) config_path_changed_cb,
 					provider ));
 
-	provider->private->monitors = list;
+	return( list );
 }
 
 /*
@@ -310,31 +278,37 @@ install_monitors( NAGConfProvider *provider )
  * xml file in gconf, or gconf is directly edited), we'd have to rely
  * only on the standard monitor (GConf watch) mechanism
  *
- * this is what we do below, thus triggering NAPivot for each and every
- * modification in the GConf underlying system ; this is the prerogative
- * of NAPivot to decide what to do with them
+ * this is what we do below, thus triggering the NAIIOProvider interface
+ * for each and every modification in the GConf underlying system ; this
+ * is the prerogative of NAIIOProvider to decide what to do with them
  */
 static void
-config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NAGConfProvider *provider )
+config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NagpGConfProvider *provider )
 {
-	/*static const gchar *thisfn = "na_gconf_provider_config_path_changed_cb";*/
+	/*static const gchar *thisfn = "nagp_gconf_provider_config_path_changed_cb";*/
+#if 0
 	NAPivotNotify *npn;
+#endif
 
 	/*g_debug( "%s: client=%p, cnxnid=%u, entry=%p, provider=%p",
 			thisfn, ( void * ) client, cnxn_id, ( void * ) entry, ( void * ) provider );*/
 
-	g_return_if_fail( NA_IS_GCONF_PROVIDER( provider ));
+	g_return_if_fail( NAGP_IS_GCONF_PROVIDER( provider ));
 	g_return_if_fail( NA_IS_IIO_PROVIDER( provider ));
 
 	if( !provider->private->dispose_has_run ){
+
+#if 0
 		npn = entry_to_notify( entry );
-		/*g_signal_emit_by_name( provider->private->pivot, NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED, npn );*/
+		g_signal_emit_by_name( provider->private->pivot, NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED, npn );
+#endif
 		na_iio_provider_config_changed( NA_IIO_PROVIDER( provider ));
 	}
 }
 
 /*
- * convert a GConfEntry to a structure suitable to notify NAPivot
+ * convert a GConfEntry to a structure suitable to notify NAIIOProvider
+ * interface
  *
  * when created or modified, the entry can be of the forms :
  *  key=path/uuid/parm
@@ -346,17 +320,19 @@ config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, N
  *  key=path/uuid/profile
  *  key=path/uuid/profile/parm with a null value
  *
- * I don't know any way to choose between key/parm and key/profile (*)
+ * I don't see any way to choose between key/parm and key/profile (*)
  * as the entry no more exists in GConf and thus cannot be tested
- * -> we will set this as key/parm, letting pivot try to interpret it
+ * -> we will set this as key/parm, letting the interface try to
+ *    interpret it
  *
  * (*) other than assuming that a profile name begins with 'profile-'
  * (see action-profile.h)
  */
+#if 0
 static NAPivotNotify *
 entry_to_notify( const GConfEntry *entry )
 {
-	/*static const gchar *thisfn = "na_gconf_entry_to_notify";*/
+	/*static const gchar *thisfn = "nagp_gconf_entry_to_notify";*/
 	GSList *listvalues, *iv, *strings;
 	NAPivotNotify *npn;
 	gchar **split;
@@ -420,9 +396,10 @@ entry_to_notify( const GConfEntry *entry )
 	}
 	return( npn );
 }
+#endif
 
 /**
- * iio_provider_read_items_list:
+ * iio_provider_read_items:
  *
  * Note that whatever be the version of the readen action, it will be
  * stored as a #NAObjectAction and its set of #NAObjectProfile of the same,
@@ -431,8 +408,8 @@ entry_to_notify( const GConfEntry *entry )
 static GList *
 iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
 {
-	static const gchar *thisfn = "na_gconf_provider_iio_provider_read_items";
-	NAGConfProvider *self;
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_read_items";
+	NagpGConfProvider *self;
 	GList *items_list = NULL;
 	GSList *listpath, *ip;
 	NAObjectItem *item;
@@ -440,8 +417,8 @@ iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
 	g_debug( "%s: provider=%p, messages=%p", thisfn, ( void * ) provider, ( void * ) messages );
 
 	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
-	g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NULL );
-	self = NA_GCONF_PROVIDER( provider );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
+	self = NAGP_GCONF_PROVIDER( provider );
 
 	if( !self->private->dispose_has_run ){
 
@@ -450,6 +427,7 @@ iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
 		for( ip = listpath ; ip ; ip = ip->next ){
 
 			const gchar *path = ( const gchar * ) ip->data;
+			g_debug( "path=%s", path );
 			item = read_item( self, path );
 			if( item ){
 				items_list = g_list_prepend( items_list, item );
@@ -463,16 +441,16 @@ iio_provider_read_items( const NAIIOProvider *provider, GSList **messages )
 }
 
 static NAObjectItem *
-read_item( NAGConfProvider *provider, const gchar *path )
+read_item( NagpGConfProvider *provider, const gchar *path )
 {
-	static const gchar *thisfn = "na_gconf_provider_read_item";
+	static const gchar *thisfn = "nagp_gconf_provider_read_item";
 	NAObjectItem *item;
 	gboolean have_type;
 	gchar *full_path;
 	gchar *type;
 
-	/*g_debug( "%s: provider=%p, path=%s", thisfn, ( void * ) provider, path );*/
-	g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NULL );
+	g_debug( "%s: provider=%p, path=%s", thisfn, ( void * ) provider, path );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NULL );
 	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
 	g_return_val_if_fail( !provider->private->dispose_has_run, NULL );
 
@@ -523,9 +501,9 @@ read_item( NAGConfProvider *provider, const gchar *path )
  * Profiles are kept in the order specified in 'items' entry if it exists.
  */
 static void
-read_item_action( NAGConfProvider *provider, const gchar *path, NAObjectAction *action )
+read_item_action( NagpGConfProvider *provider, const gchar *path, NAObjectAction *action )
 {
-	static const gchar *thisfn = "na_gconf_provider_read_item_action";
+	static const gchar *thisfn = "nagp_gconf_provider_read_item_action";
 	gchar *uuid;
 	GSList *entries, *list_profiles, *ip;
 	GSList *order;
@@ -583,7 +561,7 @@ read_item_action( NAGConfProvider *provider, const gchar *path, NAObjectAction *
  * versions
  */
 static void
-read_item_action_properties( NAGConfProvider *provider, GSList *entries, NAObjectAction *action )
+read_item_action_properties( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action )
 {
 	gchar *version;
 	gboolean target_selection, target_background, target_toolbar;
@@ -634,7 +612,7 @@ read_item_action_properties( NAGConfProvider *provider, GSList *entries, NAObjec
  * if version greater than "1.0", we have also matchcase+mimetypes
  */
 static void
-read_item_action_properties_v1( NAGConfProvider *provider, GSList *entries, NAObjectAction *action )
+read_item_action_properties_v1( NagpGConfProvider *provider, GSList *entries, NAObjectAction *action )
 {
 	NAObjectProfile *profile = na_object_profile_new();
 
@@ -644,7 +622,7 @@ read_item_action_properties_v1( NAGConfProvider *provider, GSList *entries, NAOb
 }
 
 static void
-read_item_action_profile( NAGConfProvider *provider, NAObjectAction *action, const gchar *path )
+read_item_action_profile( NagpGConfProvider *provider, NAObjectAction *action, const gchar *path )
 {
 	NAObjectProfile *profile;
 	gchar *name;
@@ -666,9 +644,9 @@ read_item_action_profile( NAGConfProvider *provider, NAObjectAction *action, con
 }
 
 static void
-read_item_action_profile_properties( NAGConfProvider *provider, GSList *entries, NAObjectProfile *profile )
+read_item_action_profile_properties( NagpGConfProvider *provider, GSList *entries, NAObjectProfile *profile )
 {
-	/*static const gchar *thisfn = "na_gconf_provider_read_item_action_profile_properties";*/
+	/*static const gchar *thisfn = "nagp_gconf_provider_read_item_action_profile_properties";*/
 	gchar *label, *path, *parameters;
 	GSList *basenames, *schemes, *mimetypes;
 	gboolean isfile, isdir, multiple, matchcase;
@@ -731,9 +709,9 @@ read_item_action_profile_properties( NAGConfProvider *provider, GSList *entries,
 }
 
 static void
-read_item_menu( NAGConfProvider *provider, const gchar *path, NAObjectMenu *menu )
+read_item_menu( NagpGConfProvider *provider, const gchar *path, NAObjectMenu *menu )
 {
-	static const gchar *thisfn = "na_gconf_provider_read_item_menu";
+	static const gchar *thisfn = "nagp_gconf_provider_read_item_menu";
 	gchar *uuid;
 	GSList *entries;
 
@@ -751,7 +729,7 @@ read_item_menu( NAGConfProvider *provider, const gchar *path, NAObjectMenu *menu
 }
 
 static void
-read_item_menu_properties( NAGConfProvider *provider, GSList *entries, NAObjectMenu *menu )
+read_item_menu_properties( NagpGConfProvider *provider, GSList *entries, NAObjectMenu *menu )
 {
 	read_object_item_properties( provider, entries, NA_OBJECT_ITEM( menu ) );
 }
@@ -760,9 +738,9 @@ read_item_menu_properties( NAGConfProvider *provider, GSList *entries, NAObjectM
  * set the properties into the NAObjectItem
  */
 static void
-read_object_item_properties( NAGConfProvider *provider, GSList *entries, NAObjectItem *item )
+read_object_item_properties( NagpGConfProvider *provider, GSList *entries, NAObjectItem *item )
 {
-	static const gchar *thisfn = "na_gconf_provider_read_object_item_properties";
+	static const gchar *thisfn = "nagp_gconf_provider_read_object_item_properties";
 	gchar *id, *label, *tooltip, *icon;
 	gboolean enabled;
 	GSList *subitems;
@@ -799,14 +777,14 @@ read_object_item_properties( NAGConfProvider *provider, GSList *entries, NAObjec
 static gboolean
 iio_provider_is_willing_to_write( const NAIIOProvider *provider )
 {
-	NAGConfProvider *self;
+	NagpGConfProvider *self;
 	gboolean willing_to = FALSE;
 
-	g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
 	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
-	self = NA_GCONF_PROVIDER( provider );
+	self = NAGP_GCONF_PROVIDER( provider );
 
-	/* TODO: na_gconf_provider_iio_provider_is_willing_to_write */
+	/* TODO: nagp_gconf_provider_iio_provider_is_willing_to_write */
 	if( !self->private->dispose_has_run ){
 		willing_to = TRUE;
 	}
@@ -817,15 +795,15 @@ iio_provider_is_willing_to_write( const NAIIOProvider *provider )
 static gboolean
 iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item )
 {
-	NAGConfProvider *self;
+	NagpGConfProvider *self;
 	gboolean willing_to = FALSE;
 
-	g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
 	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
-	self = NA_GCONF_PROVIDER( provider );
+	self = NAGP_GCONF_PROVIDER( provider );
 
-	/* TODO: na_gconf_provider_iio_provider_is_writable */
+	/* TODO: nagp_gconf_provider_iio_provider_is_writable */
 	if( !self->private->dispose_has_run ){
 		willing_to = TRUE;
 	}
@@ -836,17 +814,17 @@ iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *ite
 static guint
 iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
 {
-	static const gchar *thisfn = "na_gconf_provider_iio_provider_write_item";
-	NAGConfProvider *self;
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_write_item";
+	NagpGConfProvider *self;
 
 	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
 			thisfn, ( void * ) provider,
 			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
-	g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
 	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
 
-	self = NA_GCONF_PROVIDER( provider );
+	self = NAGP_GCONF_PROVIDER( provider );
 
 	if( self->private->dispose_has_run ){
 		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
@@ -870,7 +848,7 @@ iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item
 }
 
 static gboolean
-write_item_action( NAGConfProvider *provider, const NAObjectAction *action, GSList **messages )
+write_item_action( NagpGConfProvider *provider, const NAObjectAction *action, GSList **messages )
 {
 	gchar *uuid, *name;
 	gboolean ret;
@@ -918,7 +896,7 @@ write_item_action( NAGConfProvider *provider, const NAObjectAction *action, GSLi
 }
 
 static gboolean
-write_item_menu( NAGConfProvider *provider, const NAObjectMenu *menu, GSList **messages )
+write_item_menu( NagpGConfProvider *provider, const NAObjectMenu *menu, GSList **messages )
 {
 	gboolean ret;
 	gchar *uuid;
@@ -935,7 +913,7 @@ write_item_menu( NAGConfProvider *provider, const NAObjectMenu *menu, GSList **m
 }
 
 static gboolean
-write_object_item( NAGConfProvider *provider, const NAObjectItem *item, GSList **messages )
+write_object_item( NagpGConfProvider *provider, const NAObjectItem *item, GSList **messages )
 {
 	gchar *uuid;
 	gboolean ret;
@@ -960,8 +938,8 @@ write_object_item( NAGConfProvider *provider, const NAObjectItem *item, GSList *
 static guint
 iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages )
 {
-	static const gchar *thisfn = "na_gconf_provider_iio_provider_delete_item";
-	NAGConfProvider *self;
+	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_delete_item";
+	NagpGConfProvider *self;
 	guint ret;
 	gchar *uuid, *path;
 	GError *error = NULL;
@@ -971,10 +949,10 @@ iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *ite
 			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
 
 	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
 
-	self = NA_GCONF_PROVIDER( provider );
+	self = NAGP_GCONF_PROVIDER( provider );
 
 	if( self->private->dispose_has_run ){
 		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
@@ -987,6 +965,7 @@ iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *ite
 	gconf_client_recursive_unset( self->private->gconf, path, 0, &error );
 	if( error ){
 		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+		*messages = g_slist_append( *messages, g_strdup( error->message ));
 		g_error_free( error );
 		error = NULL;
 	}
@@ -996,8 +975,9 @@ iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *ite
 	path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
 	if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
 		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
-		/* TODO: *message = g_strdup( error->message );*/
+		*messages = g_slist_append( *messages, g_strdup( error->message ));
 		g_error_free( error );
+		error = NULL;
 		ret = NA_IIO_PROVIDER_WRITE_ERROR;
 
 	} else {
@@ -1032,9 +1012,9 @@ iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem *ite
  *    present.
  */
 static gboolean
-key_is_writable( NAGConfProvider *gconf, const gchar *path )
+key_is_writable( NagpGConfProvider *gconf, const gchar *path )
 {
-	/*static const gchar *thisfn = "na_gconf_provider_key_is_writable";
+	/*static const gchar *thisfn = "nagp_gconf_provider_key_is_writable";
 	GError *error = NULL;
 
 	remove_gconf_watched_dir( gconf );
@@ -1066,7 +1046,7 @@ key_is_writable( NAGConfProvider *gconf, const gchar *path )
 }
 
 static gboolean
-write_str( NAGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **messages )
+write_str( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, GSList **messages )
 {
 	gchar *path;
 	gboolean ret;
@@ -1081,7 +1061,7 @@ write_str( NAGConfProvider *provider, const gchar *uuid, const gchar *name, cons
 	msg = NULL;
 	ret = na_gconf_utils_write_string( provider->private->gconf, path, value, &msg );
 	if( msg ){
-		*messages = g_slist_append( *messages, msg );
+		*messages = g_slist_append( *messages, g_strdup( msg ));
 		g_free( msg );
 	}
 
@@ -1092,7 +1072,7 @@ write_str( NAGConfProvider *provider, const gchar *uuid, const gchar *name, cons
 }
 
 static gboolean
-write_bool( NAGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **messages )
+write_bool( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, GSList **messages )
 {
 	gboolean ret;
 	gchar *path;
@@ -1107,7 +1087,7 @@ write_bool( NAGConfProvider *provider, const gchar *uuid, const gchar *name, con
 	msg = NULL;
 	ret = na_gconf_utils_write_bool( provider->private->gconf, path, value, &msg );
 	if( msg ){
-		*messages = g_slist_append( *messages, msg );
+		*messages = g_slist_append( *messages, g_strdup( msg ));
 		g_free( msg );
 	}
 
@@ -1117,7 +1097,7 @@ write_bool( NAGConfProvider *provider, const gchar *uuid, const gchar *name, con
 }
 
 static gboolean
-write_list( NAGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **messages )
+write_list( NagpGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, GSList **messages )
 {
 	gboolean ret;
 	gchar *path;
@@ -1132,7 +1112,7 @@ write_list( NAGConfProvider *provider, const gchar *uuid, const gchar *name, con
 	msg = NULL;
 	ret = na_gconf_utils_write_string_list( provider->private->gconf, path, value, &msg );
 	if( msg ){
-		*messages = g_slist_append( *messages, msg );
+		*messages = g_slist_append( *messages, g_strdup( msg ));
 		g_free( msg );
 	}
 
@@ -1141,3 +1121,107 @@ write_list( NAGConfProvider *provider, const gchar *uuid, const gchar *name, con
 
 	return( ret );
 }
+
+/**
+ * na_gconf_utils_get_subdirs:
+ * @gconf: a  #GConfClient instance.
+ * @path: a full path to be readen.
+ *
+ * Loads the subdirs of the given path.
+ *
+ * Returns: a GSList of full path subdirectories.
+ *
+ * The returned list should be na_gconf_utils_free_subdirs() by the
+ * caller.
+ */
+static GSList *
+na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path )
+{
+	static const gchar *thisfn = "na_gconf_utils_get_subdirs";
+	GError *error = NULL;
+	GSList *list_subdirs;
+
+	list_subdirs = gconf_client_all_dirs( gconf, path, &error );
+
+	if( error ){
+		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+		g_error_free( error );
+		return(( GSList * ) NULL );
+	}
+
+	return( list_subdirs );
+}
+
+/**
+ * na_gconf_utils_free_subdirs:
+ * @subdirs: a list of subdirs as returned by na_gconf_utils_get_subdirs().
+ *
+ * Release the list of subdirs.
+ */
+static void
+na_gconf_utils_free_subdirs( GSList *subdirs )
+{
+	na_utils_free_string_list( subdirs );
+}
+
+/**
+ * na_gconf_utils_have_subdir:
+ * @gconf: a  #GConfClient instance.
+ * @path: a full path to be readen.
+ *
+ * Returns: %TRUE if the specified path has at least one subdirectory,
+ * %FALSE else.
+ */
+/*static gboolean
+na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path )
+{
+	GSList *listpath;
+	gboolean have_subdir;
+
+	listpath = na_gconf_utils_get_subdirs( gconf, path );
+	have_subdir = ( listpath && g_slist_length( listpath ));
+	na_gconf_utils_free_subdirs( listpath );
+
+	return( have_subdir );
+}*/
+
+/**
+ * na_gconf_utils_have_entry:
+ * @gconf: a  #GConfClient instance.
+ * @path: the full path of a key.
+ * @entry: the entry to be tested.
+ *
+ * Returns: %TRUE if the given @entry exists for the given @path,
+ * %FALSE else.
+ */
+static gboolean
+na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry )
+{
+	static const gchar *thisfn = "na_gconf_utils_have_entry";
+	gboolean have_entry = FALSE;
+	GError *error = NULL;
+	gchar *key;
+	GConfValue *value;
+
+	key = g_strdup_printf( "%s/%s", path, entry );
+
+	value = gconf_client_get_without_default( gconf, key, &error );
+
+	if( error ){
+		g_warning( "%s: key=%s, error=%s", thisfn, key, error->message );
+		g_error_free( error );
+		if( value ){
+			gconf_value_free( value );
+			value = NULL;
+		}
+	}
+
+	if( value ){
+		have_entry = TRUE;
+		gconf_value_free( value );
+	}
+
+	g_free( key );
+
+	return( have_entry );
+}
diff --git a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h
new file mode 100644
index 0000000..0030e35
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.h
@@ -0,0 +1,80 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifndef __NAGP_GCONF_PROVIDER_H__
+#define __NAGP_GCONF_PROVIDER_H__
+
+/**
+ * SECTION: nagp_gconf_provider
+ * @short_description: #NagpGConfProvider class definition.
+ * @include: na-gconf-provider.h
+ *
+ * This class manages the GConf I/O storage subsystem, or, in other words,
+ * the GConf subsystem as an NAIIOProvider. As this, it should only be
+ * used through the NAIIOProvider interface.
+ *
+ * #NagpGConfProvider uses #NAGConfMonitor to watch at the configuration
+ * tree. Modifications are notified to the NAIIOProvider interface.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NAGP_GCONF_PROVIDER_TYPE				( nagp_gconf_provider_get_type())
+#define NAGP_GCONF_PROVIDER( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NAGP_GCONF_PROVIDER_TYPE, NagpGConfProvider ))
+#define NAGP_GCONF_PROVIDER_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NAGP_GCONF_PROVIDER_TYPE, NagpGConfProviderClass ))
+#define NAGP_IS_GCONF_PROVIDER( object )		( G_TYPE_CHECK_INSTANCE_TYPE( object, NAGP_GCONF_PROVIDER_TYPE ))
+#define NAGP_IS_GCONF_PROVIDER_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NAGP_GCONF_PROVIDER_TYPE ))
+#define NAGP_GCONF_PROVIDER_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NAGP_GCONF_PROVIDER_TYPE, NagpGConfProviderClass ))
+
+typedef struct NagpGConfProviderPrivate NagpGConfProviderPrivate;
+
+typedef struct {
+	GObject                   parent;
+	NagpGConfProviderPrivate *private;
+}
+	NagpGConfProvider;
+
+typedef struct NagpGConfProviderClassPrivate NagpGConfProviderClassPrivate;
+
+typedef struct {
+	GObjectClass                   parent;
+	NagpGConfProviderClassPrivate *private;
+}
+	NagpGConfProviderClass;
+
+GType nagp_gconf_provider_get_type     ( void );
+void  nagp_gconf_provider_register_type( GTypeModule *module );
+
+G_END_DECLS
+
+#endif /* __NAGP_GCONF_PROVIDER_H__ */
diff --git a/nautilus-actions/runtime/na-gconf-provider-keys.h b/nautilus-actions/io-provider-gconf/nagp-keys.h
similarity index 72%
rename from nautilus-actions/runtime/na-gconf-provider-keys.h
rename to nautilus-actions/io-provider-gconf/nagp-keys.h
index 04149cd..8ff5579 100644
--- a/nautilus-actions/runtime/na-gconf-provider-keys.h
+++ b/nautilus-actions/io-provider-gconf/nagp-keys.h
@@ -28,10 +28,10 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_RUNTIME_GCONF_PROVIDER_KEYS_H__
-#define __NA_RUNTIME_GCONF_PROVIDER_KEYS_H__
+#ifndef __NAGP_GCONF_PROVIDER_KEYS_H__
+#define __NAGP_GCONF_PROVIDER_KEYS_H__
 
-#include <api/na-gconf-keys.h>
+#include <nautilus-actions/api/na-gconf-keys.h>
 
 /* GConf general information
  */
@@ -51,28 +51,28 @@
 #define OBJECT_ITEM_TOOLBAR_SAME_LABEL_ENTRY	"toolbar-same-label"
 #define OBJECT_ITEM_TOOLBAR_LABEL_ENTRY			"toolbar-label"
 
-#define OBJECT_ITEM_TYPE_MENU			"Menu"
-#define OBJECT_ITEM_TYPE_ACTION			"Action"
+#define OBJECT_ITEM_TYPE_MENU					"Menu"
+#define OBJECT_ITEM_TYPE_ACTION					"Action"
 
 /* GConf key names (specific to menu)
  */
 
 /* GConf key names (specific to action)
  */
-#define ACTION_VERSION_ENTRY			"version"
+#define ACTION_VERSION_ENTRY					"version"
 
 /* GConf key names (specific to profile)
  */
-#define ACTION_PROFILE_LABEL_ENTRY		"desc-name"
-#define ACTION_PATH_ENTRY				"path"
-#define ACTION_PARAMETERS_ENTRY			"parameters"
-#define ACTION_BASENAMES_ENTRY			"basenames"
-#define ACTION_MATCHCASE_ENTRY			"matchcase"
-#define ACTION_MIMETYPES_ENTRY			"mimetypes"
-#define ACTION_ISFILE_ENTRY				"isfile"
-#define ACTION_ISDIR_ENTRY				"isdir"
-#define ACTION_MULTIPLE_ENTRY			"accept-multiple-files"
-#define ACTION_SCHEMES_ENTRY			"schemes"
-#define ACTION_FOLDERS_ENTRY			"folders"
+#define ACTION_PROFILE_LABEL_ENTRY				"desc-name"
+#define ACTION_PATH_ENTRY						"path"
+#define ACTION_PARAMETERS_ENTRY					"parameters"
+#define ACTION_BASENAMES_ENTRY					"basenames"
+#define ACTION_MATCHCASE_ENTRY					"matchcase"
+#define ACTION_MIMETYPES_ENTRY					"mimetypes"
+#define ACTION_ISFILE_ENTRY						"isfile"
+#define ACTION_ISDIR_ENTRY						"isdir"
+#define ACTION_MULTIPLE_ENTRY					"accept-multiple-files"
+#define ACTION_SCHEMES_ENTRY					"schemes"
+#define ACTION_FOLDERS_ENTRY					"folders"
 
-#endif /* __NA_RUNTIME_GCONF_PROVIDER_KEYS_H__ */
+#endif /* __NAGP_GCONF_PROVIDER_KEYS_H__ */
diff --git a/nautilus-actions/io-provider-gconf/nagp-module.c b/nautilus-actions/io-provider-gconf/nagp-module.c
new file mode 100644
index 0000000..2430fa5
--- /dev/null
+++ b/nautilus-actions/io-provider-gconf/nagp-module.c
@@ -0,0 +1,160 @@
+/*
+ * Nautilus Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <syslog.h>
+
+#include <nautilus-actions/api/na-api.h>
+
+#include "nagp-gconf-provider.h"
+
+static guint st_log_handler_api = 0;
+static guint st_log_handler_plugin = 0;
+
+static void setup_log_handler( const gchar *log_domain, guint *handler_id );
+static void remove_log_handler( guint *handler_id );
+static void nagp_log_handler( const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data );
+
+/*
+ * A Nautilus-Actions extension must implement four functions :
+ *
+ * - na_api_module_init
+ * - na_api_module_list_types
+ * - na_api_module_get_name
+ * - na_api_module_shutdown
+ *
+ * The first two functions are called at Nautilus-Actions startup.
+ *
+ * The prototypes for these functions are defined in nautilus-actions/na-api.h
+ */
+
+gboolean
+na_api_module_init( GTypeModule *module )
+{
+	static const gchar *thisfn = "nagp_module_na_api_module_initialize";
+	static const gchar *name = "NagpGConfIOProvider";
+
+	syslog( LOG_USER | LOG_INFO, "%s initializing...", name );
+
+	openlog( G_LOG_DOMAIN, LOG_PID, LOG_USER );
+
+	setup_log_handler( NA_LOGDOMAIN_API, &st_log_handler_api );
+	setup_log_handler( NA_LOGDOMAIN_IO_PROVIDER_GCONF, &st_log_handler_plugin );
+
+	g_debug( "%s: module=%p", thisfn, ( void * ) module );
+
+	g_type_module_set_name( module, name );
+
+	nagp_gconf_provider_register_type( module );
+
+	return( TRUE );
+}
+
+gint
+na_api_module_list_types( const GType **types )
+{
+	static const gchar *thisfn = "nagp_module_na_api_module_list_types";
+	#define count 1
+	static GType type_list[count];
+
+	g_debug( "%s: types=%p", thisfn, ( void * ) types );
+
+	type_list[0] = NAGP_GCONF_PROVIDER_TYPE;
+	*types = type_list;
+
+	return( count );
+}
+
+const gchar *
+na_api_module_get_name( GType type )
+{
+	static const gchar *thisfn = "nagp_module_na_api_module_get_name";
+
+	g_debug( "%s: type=%ld", thisfn, ( gulong ) type );
+
+	if( type == NAGP_GCONF_PROVIDER_TYPE ){
+		return( "Nautilus Actions GConf Provider" );
+	}
+
+	return( NULL );
+}
+
+void
+na_api_module_shutdown( void )
+{
+	static const gchar *thisfn = "nagp_module_na_api_module_shutdown";
+
+	g_debug( "%s", thisfn );
+
+	/* remove the log handler
+	 * almost useless as the process is nonetheless terminating at this time
+	 * but this is the art of coding...
+	 */
+	remove_log_handler( &st_log_handler_api );
+	remove_log_handler( &st_log_handler_plugin );
+}
+
+static void
+setup_log_handler( const gchar *log_domain, guint *handler_id )
+{
+	*handler_id = g_log_set_handler( log_domain, G_LOG_LEVEL_DEBUG, nagp_log_handler, NULL );
+}
+
+static void
+remove_log_handler( guint *handler_id )
+{
+	if( *handler_id ){
+		g_log_remove_handler( G_LOG_DOMAIN, *handler_id );
+		*handler_id = 0;
+	}
+}
+
+/*
+ * a log handler that we install when in development mode in order to be
+ * able to log plugin runtime
+ * TODO: the debug flag should be dynamic, so that an advanced user could
+ * setup a given key and obtain a full log to send to Bugzilla..
+ * For now, is always install when compiled in maintainer mode, never else
+ */
+static void
+nagp_log_handler( const gchar *log_domain,
+					GLogLevelFlags log_level,
+					const gchar *message,
+					gpointer user_data )
+{
+#ifdef NA_MAINTAINER_MODE
+	syslog( LOG_USER | LOG_DEBUG, "%s", message );
+#else
+	/* do nothing */
+#endif
+}
diff --git a/nautilus-actions/nact/nact-xml-reader.c b/nautilus-actions/nact/nact-xml-reader.c
index 152b407..add806e 100644
--- a/nautilus-actions/nact/nact-xml-reader.c
+++ b/nautilus-actions/nact/nact-xml-reader.c
@@ -40,7 +40,8 @@
 
 #include <api/na-object-api.h>
 
-#include <runtime/na-gconf-provider-keys.h>
+#include <io-provider-gconf/nagp-keys.h>
+
 #include <runtime/na-gconf-utils.h>
 #include <runtime/na-iprefs.h>
 #include <runtime/na-utils.h>
diff --git a/nautilus-actions/plugin/nautilus-actions.h b/nautilus-actions/plugin/nautilus-actions.h
index 8a4490c..eabde62 100644
--- a/nautilus-actions/plugin/nautilus-actions.h
+++ b/nautilus-actions/plugin/nautilus-actions.h
@@ -77,7 +77,7 @@ typedef struct
 }
 	NautilusActionsClass;
 
-GType nautilus_actions_get_type( void );
+GType nautilus_actions_get_type     ( void );
 void  nautilus_actions_register_type( GTypeModule *module );
 
 G_END_DECLS
diff --git a/nautilus-actions/plugin/nautilus-module.c b/nautilus-actions/plugin/nautilus-module.c
index 005e60d..abc873f 100644
--- a/nautilus-actions/plugin/nautilus-module.c
+++ b/nautilus-actions/plugin/nautilus-module.c
@@ -69,6 +69,8 @@ nautilus_module_initialize( GTypeModule *module )
 
 	g_debug( "%s: module=%p", thisfn, ( void * ) module );
 
+	g_type_module_set_name( module, PACKAGE_STRING );
+
 	nautilus_actions_register_type( module );
 }
 
diff --git a/nautilus-actions/runtime/Makefile.am b/nautilus-actions/runtime/Makefile.am
index 4b20618..8a6c177 100644
--- a/nautilus-actions/runtime/Makefile.am
+++ b/nautilus-actions/runtime/Makefile.am
@@ -38,9 +38,6 @@ AM_CPPFLAGS += \
 	$(NULL)
 
 libna_runtime_la_SOURCES = \
-	na-gconf-provider.c											\
-	na-gconf-provider.h											\
-	na-gconf-provider-keys.h									\
 	na-gconf-utils.c											\
 	na-gconf-utils.h											\
 	na-iabout.c													\
diff --git a/nautilus-actions/runtime/na-gconf-utils.c b/nautilus-actions/runtime/na-gconf-utils.c
index d2c5a29..052f631 100644
--- a/nautilus-actions/runtime/na-gconf-utils.c
+++ b/nautilus-actions/runtime/na-gconf-utils.c
@@ -41,69 +41,6 @@ static GConfValue *read_value( GConfClient *gconf, const gchar *path, gboolean u
 static gboolean    sync_gconf( GConfClient *gconf, gchar **message );
 
 /**
- * na_gconf_utils_get_subdirs:
- * @gconf: a  #GConfClient instance.
- * @path: a full path to be readen.
- *
- * Loads the subdirs of the given path.
- *
- * Returns: a GSList of full path subdirectories.
- *
- * The returned list should be na_gconf_utils_free_subdirs() by the
- * caller.
- */
-GSList *
-na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path )
-{
-	static const gchar *thisfn = "na_gconf_utils_get_subdirs";
-	GError *error = NULL;
-	GSList *list_subdirs;
-
-	list_subdirs = gconf_client_all_dirs( gconf, path, &error );
-
-	if( error ){
-		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
-		g_error_free( error );
-		return(( GSList * ) NULL );
-	}
-
-	return( list_subdirs );
-}
-
-/**
- * na_gconf_utils_free_subdirs:
- * @subdirs: a list of subdirs as returned by na_gconf_utils_get_subdirs().
- *
- * Release the list of subdirs.
- */
-void
-na_gconf_utils_free_subdirs( GSList *subdirs )
-{
-	na_utils_free_string_list( subdirs );
-}
-
-/**
- * na_gconf_utils_have_subdir:
- * @gconf: a  #GConfClient instance.
- * @path: a full path to be readen.
- *
- * Returns: %TRUE if the specified path has at least one subdirectory,
- * %FALSE else.
- */
-gboolean
-na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path )
-{
-	GSList *listpath;
-	gboolean have_subdir;
-
-	listpath = na_gconf_utils_get_subdirs( gconf, path );
-	have_subdir = ( listpath && g_slist_length( listpath ));
-	na_gconf_utils_free_subdirs( listpath );
-
-	return( have_subdir );
-}
-
-/**
  * na_gconf_utils_get_entries:
  * @gconf: a  #GConfClient instance.
  * @path: a full path to be readen.
@@ -148,47 +85,6 @@ na_gconf_utils_free_entries( GSList *list )
 }
 
 /**
- * na_gconf_utils_have_entry:
- * @gconf: a  #GConfClient instance.
- * @path: the full path of a key.
- * @entry: the entry to be tested.
- *
- * Returns: %TRUE if the given @entry exists for the given @path,
- * %FALSE else.
- */
-gboolean
-na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry )
-{
-	static const gchar *thisfn = "na_gconf_utils_have_entry";
-	gboolean have_entry = FALSE;
-	GError *error = NULL;
-	gchar *key;
-	GConfValue *value;
-
-	key = g_strdup_printf( "%s/%s", path, entry );
-
-	value = gconf_client_get_without_default( gconf, key, &error );
-
-	if( error ){
-		g_warning( "%s: key=%s, error=%s", thisfn, key, error->message );
-		g_error_free( error );
-		if( value ){
-			gconf_value_free( value );
-			value = NULL;
-		}
-	}
-
-	if( value ){
-		have_entry = TRUE;
-		gconf_value_free( value );
-	}
-
-	g_free( key );
-
-	return( have_entry );
-}
-
-/**
  * na_gconf_utils_get_bool_from_entries:
  * @entries: a list of #GConfEntry as returned by na_gconf_utils_get_entries().
  * @entry: the searched entry.
diff --git a/nautilus-actions/runtime/na-gconf-utils.h b/nautilus-actions/runtime/na-gconf-utils.h
index b3427a7..c4c050d 100644
--- a/nautilus-actions/runtime/na-gconf-utils.h
+++ b/nautilus-actions/runtime/na-gconf-utils.h
@@ -40,13 +40,8 @@
 #include <gconf/gconf.h>
 #include <gconf/gconf-client.h>
 
-GSList  *na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path );
-void     na_gconf_utils_free_subdirs( GSList *subdirs );
-gboolean na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path );
-
 GSList  *na_gconf_utils_get_entries( GConfClient *gconf, const gchar *path );
 void     na_gconf_utils_free_entries( GSList *entries );
-gboolean na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry );
 gboolean na_gconf_utils_get_bool_from_entries( GSList *entries, const gchar *entry, gboolean *value );
 gboolean na_gconf_utils_get_string_from_entries( GSList *entries, const gchar *entry, gchar **value );
 gboolean na_gconf_utils_get_string_list_from_entries( GSList *entries, const gchar *entry, GSList **value );
diff --git a/nautilus-actions/runtime/na-module.c b/nautilus-actions/runtime/na-module.c
index e6ecd21..c62dc64 100644
--- a/nautilus-actions/runtime/na-module.c
+++ b/nautilus-actions/runtime/na-module.c
@@ -46,7 +46,7 @@ struct NAModuleClassPrivate {
  */
 struct NAModulePrivate {
 	gboolean  dispose_has_run;
-	gchar    *path;
+	gchar    *path;						/* full pathname of the plugin */
 	GModule  *library;
 	GList    *objects;
 
@@ -66,15 +66,15 @@ static void      instance_init( GTypeInstance *instance, gpointer klass );
 static void      instance_dispose( GObject *object );
 static void      instance_finalize( GObject *object );
 
+static NAModule *module_new( const gchar *filename );
 static gboolean  module_load( GTypeModule *gmodule );
-static gboolean  module_load_check( NAModule *module, const gchar *symbol, gpointer *pfn );
-static void      module_unload( GTypeModule *gmodule );
-
-static void      add_module_objects( NAModule *module );
+static gboolean  is_a_na_plugin( NAModule *module );
+static gboolean  plugin_check( NAModule *module, const gchar *symbol, gpointer *pfn );
+static void      register_module_types( NAModule *module );
 static void      add_module_type( NAModule *module, GType type );
-static NAModule *module_new( const gchar *filename );
-static void      module_object_weak_notify( NAModule *module, GObject *object );
-static void      set_name( NAModule *module );
+static void      object_weak_notify( NAModule *module, GObject *object );
+
+static void      module_unload( GTypeModule *gmodule );
 
 GType
 na_module_get_type( void )
@@ -164,6 +164,8 @@ instance_dispose( GObject *object )
 
 		self->private->dispose_has_run = TRUE;
 
+		g_type_module_unuse( G_TYPE_MODULE( self ));
+
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
 			G_OBJECT_CLASS( st_parent_class )->dispose( object );
@@ -191,79 +193,10 @@ instance_finalize( GObject *object )
 	}
 }
 
-/*
- * triggered by GTypeModule base class when first loading the library
- * which is itself triggered by module_new:g_type_module_use()
- */
-static gboolean
-module_load( GTypeModule *gmodule )
-{
-	static const gchar *thisfn = "na_module_module_load";
-	NAModule *module;
-	gboolean loaded;
-
-	g_debug( "%s: gmodule=%p", thisfn, ( void * ) gmodule );
-	g_return_val_if_fail( G_IS_TYPE_MODULE( gmodule ), FALSE );
-
-	module = NA_MODULE( gmodule );
-
-	module->private->library = g_module_open( module->private->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL );
-
-	if( !module->private->library ){
-		g_warning( "%s: g_module_open: path=%s, error=%s", thisfn, module->private->path, g_module_error());
-		return( FALSE );
-	}
-
-	loaded =
-		module_load_check( module, "na_api_module_init", ( gpointer * ) &module->private->initialize) &&
-		module_load_check( module, "na_api_module_list_types", ( gpointer * ) &module->private->list_types ) &&
-		module_load_check( module, "na_api_module_get_name", ( gpointer * ) &module->private->get_name ) &&
-		module_load_check( module, "na_api_module_shutdown", ( gpointer * ) &module->private->shutdown ) &&
-		module->private->initialize( gmodule );
-
-	return( loaded );
-}
-
-static gboolean
-module_load_check( NAModule *module, const gchar *symbol, gpointer *pfn )
-{
-	static const gchar *thisfn = "na_module_module_load_check";
-	gboolean ok;
-
-	ok = g_module_symbol( module->private->library, symbol, pfn );
-	if( !ok ){
-		g_debug("%s: %s: symbol not found in %s", thisfn, symbol, module->private->path );
-		g_module_close( module->private->library );
-	}
-
-	return( ok );
-}
-
-static void
-module_unload( GTypeModule *gmodule )
-{
-	static const gchar *thisfn = "na_module_module_unload";
-	NAModule *module;
-
-	g_debug( "%s: gmodule=%p", thisfn, ( void * ) gmodule );
-	g_return_if_fail( G_IS_TYPE_MODULE( gmodule ));
-
-	module = NA_MODULE( gmodule );
-
-	module->private->shutdown();
-
-	g_module_close( module->private->library );
-
-	module->private->initialize = NULL;
-	module->private->list_types = NULL;
-	module->private->get_name = NULL;
-	module->private->shutdown = NULL;
-}
-
 /**
  * na_module_load_modules:
  *
- * Load availables dynamic libraries.
+ * Load availables dynamically loadable extension libraries (plugins).
  *
  * Returns: a #GList of #NAModule, each object representing a dynamically
  * loaded library.
@@ -310,73 +243,104 @@ na_module_load_modules( void )
 	return( modules );
 }
 
-/**
- * na_module_get_extensions_for_type:
- * @type: the serched GType.
- *
- * Returns: a list of loaded modules willing to deal with requested @type.
+/*
+ * @fname: full pathname of the being-loaded dynamic library.
  */
-GList *
-na_module_get_extensions_for_type( GList *modules, GType type )
+static NAModule *
+module_new( const gchar *fname )
 {
-	GList *willing_to, *im;
+	NAModule *module;
 
-	willing_to = NULL;
+	module = g_object_new( NA_MODULE_TYPE, NULL );
+	module->private->path = g_strdup( fname );
 
-	for( im = modules; im ; im = im->next ){
-		if( G_TYPE_CHECK_INSTANCE_TYPE( G_OBJECT( im->data ), type )){
-			g_object_ref( im->data );
-			willing_to = g_list_prepend( willing_to, im->data );
-		}
+	if( !g_type_module_use( G_TYPE_MODULE( module )) || !is_a_na_plugin( module )){
+
+		g_object_unref( module );
+		return( NULL );
 	}
 
-	willing_to = g_list_reverse( willing_to );
+	register_module_types( module );
 
-	return( willing_to );
+	return( module );
 }
 
-/**
- * na_module_get_name:
- * @module: the #NAModule instance corresponding to a dynamically
- *  loaded library.
- * @type: one the #GType this @module advertizes it implements.
+/*
+ * triggered by GTypeModule base class when first loading the library,
+ * which is itself triggered by module_new:g_type_module_use()
  *
- * Returns: the name the #NAModule @module applies to itself for this
- * @type, as a newly allocated string which should be g_free() by the
- * caller.
+ * returns: %TRUE if the module is successfully loaded
  */
-gchar *
-na_module_get_name( NAModule *module, GType type )
+static gboolean
+module_load( GTypeModule *gmodule )
 {
-	gchar *name = NULL;
+	static const gchar *thisfn = "na_module_module_load";
+	NAModule *module;
+	gboolean loaded;
 
-	g_return_val_if_fail( NA_IS_MODULE( module ), name );
+	g_debug( "%s: gmodule=%p", thisfn, ( void * ) gmodule );
+	g_return_val_if_fail( G_IS_TYPE_MODULE( gmodule ), FALSE );
 
-	name = g_strdup( module->private->get_name( type ));
+	loaded = FALSE;
+	module = NA_MODULE( gmodule );
 
-	return( name );
+	module->private->library = g_module_open( module->private->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL );
+
+	if( !module->private->library ){
+		g_warning( "%s: g_module_open: path=%s, error=%s", thisfn, module->private->path, g_module_error());
+	} else {
+		loaded = TRUE;
+	}
+
+	return( loaded );
 }
 
-/**
- * na_module_release_modules:
- * @modules: the list of loaded modules.
- *
- * Release resources allocated to the loaded modules.
+/*
+ * the module has been successfully loaded
+ * is it a Nautilus-Action plugin ?
+ * if ok, we ask the plugin to initialize itself
  */
-void
-na_module_release_modules( GList *modules )
+static gboolean
+is_a_na_plugin( NAModule *module )
 {
-	GList *im;
+	gboolean ok;
 
-	for( im = modules ; im ; im = im->next ){
-		g_object_unref( NA_MODULE( im->data ));
+	ok =
+		plugin_check( module, "na_api_module_init"      , ( gpointer * ) &module->private->initialize) &&
+		plugin_check( module, "na_api_module_list_types", ( gpointer * ) &module->private->list_types ) &&
+		plugin_check( module, "na_api_module_get_name"  , ( gpointer * ) &module->private->get_name ) &&
+		plugin_check( module, "na_api_module_shutdown"  , ( gpointer * ) &module->private->shutdown ) &&
+		module->private->initialize( G_TYPE_MODULE( module ));
+
+	return( ok );
+}
+
+static gboolean
+plugin_check( NAModule *module, const gchar *symbol, gpointer *pfn )
+{
+	static const gchar *thisfn = "na_module_plugin_check";
+	gboolean ok;
+
+	ok = g_module_symbol( module->private->library, symbol, pfn );
+
+	if( !ok ){
+		g_debug("%s: %s: %s: symbol", thisfn, module->private->path, symbol );
 	}
 
-	g_list_free( modules );
+	return( ok );
 }
 
+/*
+ * the 'na_api_module_init' function of the plugin has been already
+ * called ; the GTypes the plugin provides have so already been declared
+ * in the GType system
+ *
+ * we ask here the plugin to give us a list of these GTypes
+ * for each GType, we allocate a new object of the given class
+ * and keep this object in the module's list
+ */
 static void
-add_module_objects( NAModule *module )
+register_module_types( NAModule *module )
 {
 	const GType *types;
 	gint count, i;
@@ -401,41 +365,129 @@ add_module_type( NAModule *module, GType type )
 	object = g_object_new( type, NULL );
 
 	g_object_weak_ref( object,
-			( GWeakNotify ) module_object_weak_notify,
+			( GWeakNotify ) object_weak_notify,
 			module );
 
 	module->private->objects = g_list_prepend( module->private->objects, object );
 }
 
-static NAModule *
-module_new( const gchar *fname )
+static void
+object_weak_notify( NAModule *module, GObject *object )
+{
+	static const gchar *thisfn = "na_module_object_weak_notify";
+
+	g_debug( "%s: module=%p, object=%p (%s)",
+			thisfn, ( void * ) module, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+
+	module->private->objects = g_list_remove( module->private->objects, object );
+}
+
+/*
+ * 'unload' is triggered by the last 'unuse' call
+ * which is itself called in na_module::instance_dispose
+ */
+static void
+module_unload( GTypeModule *gmodule )
 {
+	static const gchar *thisfn = "na_module_module_unload";
 	NAModule *module;
 
-	module = g_object_new( NA_MODULE_TYPE, NULL );
-	module->private->path = g_strdup( fname );
+	g_debug( "%s: gmodule=%p", thisfn, ( void * ) gmodule );
+	g_return_if_fail( G_IS_TYPE_MODULE( gmodule ));
 
-	if( g_type_module_use( G_TYPE_MODULE( module ))){
-		add_module_objects( module );
-		set_name( module );
-		g_type_module_unuse( G_TYPE_MODULE( module ));
+	module = NA_MODULE( gmodule );
 
-	} else {
-		g_object_unref( module );
-		module = NULL;
+	if( module->private->shutdown ){
+		module->private->shutdown();
 	}
 
-	return( module );
+	if( module->private->library ){
+		g_module_close( module->private->library );
+	}
+
+	module->private->initialize = NULL;
+	module->private->list_types = NULL;
+	module->private->get_name = NULL;
+	module->private->shutdown = NULL;
 }
 
-static void
-module_object_weak_notify( NAModule *module, GObject *object )
+/**
+ * na_module_get_extensions_for_type:
+ * @type: the serched GType.
+ *
+ * Returns: a list of loaded modules willing to deal with requested @type.
+ */
+GList *
+na_module_get_extensions_for_type( GList *modules, GType type )
 {
-	module->private->objects = g_list_remove( module->private->objects, object );
+	GList *willing_to, *im, *io;
+	NAModule *a_modul;
+
+	willing_to = NULL;
+
+	for( im = modules; im ; im = im->next ){
+		a_modul = NA_MODULE( im->data );
+		for( io = a_modul->private->objects ; io ; io = io->next ){
+			if( G_TYPE_CHECK_INSTANCE_TYPE( G_OBJECT( io->data ), type )){
+				willing_to = g_list_prepend( willing_to, g_object_ref( io->data ));
+			}
+		}
+	}
+
+	willing_to = g_list_reverse( willing_to );
+
+	return( willing_to );
 }
 
-static void
-set_name( NAModule *module )
+/**
+ * na_module_free_extensions_list:
+ * @extensions: a #GList as returned by #na_module_get_extensions_for_type().
+ *
+ * Free the previously returned list.
+ */
+void
+na_module_free_extensions_list( GList *extensions )
+{
+	g_list_foreach( extensions, ( GFunc ) g_object_unref, NULL );
+	g_list_free( extensions );
+}
+
+/**
+ * na_module_get_name:
+ * @module: the #NAModule instance corresponding to a dynamically
+ *  loaded library.
+ * @type: one the #GType this @module advertizes it implements.
+ *
+ * Returns: the name the #NAModule @module applies to itself for this
+ * @type, as a newly allocated string which should be g_free() by the
+ * caller.
+ */
+gchar *
+na_module_get_name( NAModule *module, GType type )
+{
+	gchar *name = NULL;
+
+	g_return_val_if_fail( NA_IS_MODULE( module ), name );
+
+	name = g_strdup( module->private->get_name( type ));
+
+	return( name );
+}
+
+/**
+ * na_module_release_modules:
+ * @modules: the list of loaded modules.
+ *
+ * Release resources allocated to the loaded modules.
+ */
+void
+na_module_release_modules( GList *modules )
 {
-	/* do we should set internal GTypeModule name here ? */
+	GList *im;
+
+	for( im = modules ; im ; im = im->next ){
+		g_object_unref( NA_MODULE( im->data ));
+	}
+
+	g_list_free( modules );
 }
diff --git a/nautilus-actions/runtime/na-module.h b/nautilus-actions/runtime/na-module.h
index 388d541..24a71b0 100644
--- a/nautilus-actions/runtime/na-module.h
+++ b/nautilus-actions/runtime/na-module.h
@@ -34,10 +34,14 @@
 /**
  * SECTION: na_module
  * @short_description: #NAModule class definition.
- * @include: common/na-module.h
+ * @include: runtime/na-module.h
  *
  * The NAModule class manages Nautilus-Actions extensions as dynamically
- * loadable modules.
+ * loadable modules (plugins).
+ *
+ * NAModule
+ *  +- is derived from GTypeModule
+ *      +- which itself implements GTypePlugin
  */
 
 #include <glib.h>
@@ -71,7 +75,10 @@ typedef struct {
 GType  na_module_get_type               ( void );
 
 GList *na_module_load_modules           ( void );
+
 GList *na_module_get_extensions_for_type( GList *modules, GType type );
+void   na_module_free_extensions_list   ( GList *extensions );
+
 gchar *na_module_get_name               ( NAModule *module, GType type );
 void   na_module_release_modules        ( GList *modules );
 
diff --git a/nautilus-actions/runtime/na-pivot.c b/nautilus-actions/runtime/na-pivot.c
index e8c28a7..5987293 100644
--- a/nautilus-actions/runtime/na-pivot.c
+++ b/nautilus-actions/runtime/na-pivot.c
@@ -39,7 +39,6 @@
 #include <api/na-gconf-monitor.h>
 
 #include "na-io-provider.h"
-#include "na-gconf-provider.h"
 #include "na-iprefs.h"
 #include "na-module.h"
 #include "na-pivot.h"
@@ -56,7 +55,7 @@ struct NAPivotClassPrivate {
 struct NAPivotPrivate {
 	gboolean dispose_has_run;
 
-	/* dynamically loaded modules
+	/* dynamically loaded modules (extension plugins)
 	 */
 	GList   *modules;
 
@@ -65,13 +64,6 @@ struct NAPivotPrivate {
 	 */
 	GList   *consumers;
 
-	/* list of NAIIOProvider interface providers
-	 * needs to be in the instance rather than in the class to be able
-	 * to pass NAPivot object to the IO provider, so that the later
-	 * is able to have access to the former (and its list of actions)
-	 */
-	GList   *providers;
-
 	/* configuration tree
 	 */
 	GList   *tree;
@@ -113,7 +105,6 @@ static NAObject *get_item_from_tree( const NAPivot *pivot, GList *tree, uuid_t u
 static void      free_consumers( GList *list );
 
 /* NAIIOProvider management */
-static void      register_io_providers( NAPivot *pivot );
 static void      action_changed_handler( NAPivot *pivot, gpointer user_data );
 static gboolean  on_actions_changed_timeout( gpointer user_data );
 static gulong    time_val_diff( const GTimeVal *recent, const GTimeVal *old );
@@ -227,7 +218,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private->dispose_has_run = FALSE;
 	self->private->modules = NULL;
 	self->private->consumers = NULL;
-	self->private->providers = NULL;
 	self->private->tree = NULL;
 	self->private->automatic_reload = FALSE;
 }
@@ -254,10 +244,6 @@ instance_dispose( GObject *object )
 		free_consumers( self->private->consumers );
 		self->private->consumers = NULL;
 
-		/* release list of NAIIOProviders */
-		na_pivot_free_providers( self->private->providers );
-		self->private->providers = NULL;
-
 		/* release item tree */
 		na_object_free_items_list( self->private->tree );
 		self->private->tree = NULL;
@@ -314,8 +300,8 @@ na_pivot_new( const NAIPivotConsumer *target )
 	pivot = g_object_new( NA_PIVOT_TYPE, NULL );
 
 	pivot->private->modules = na_module_load_modules();
-
-	register_io_providers( pivot );
+	/*g_debug( "%s: modules=%p, count=%d",
+			thisfn, ( void * ) pivot->private->modules, g_list_length( pivot->private->modules ));*/
 
 	if( target ){
 		na_pivot_register_consumer( pivot, target );
@@ -372,7 +358,6 @@ na_pivot_dump( const NAPivot *pivot )
 
 		g_debug( "%s:   modules=%p (%d elts)", thisfn, ( void * ) pivot->private->modules, g_list_length( pivot->private->modules ));
 		g_debug( "%s: consumers=%p (%d elts)", thisfn, ( void * ) pivot->private->consumers, g_list_length( pivot->private->consumers ));
-		g_debug( "%s: providers=%p (%d elts)", thisfn, ( void * ) pivot->private->providers, g_list_length( pivot->private->providers ));
 		g_debug( "%s:      tree=%p (%d elts)", thisfn, ( void * ) pivot->private->tree, g_list_length( pivot->private->tree ));
 
 		for( it = pivot->private->tree, i = 0 ; it ; it = it->next ){
@@ -399,18 +384,14 @@ na_pivot_get_providers( const NAPivot *pivot, GType type )
 {
 	static const gchar *thisfn = "na_pivot_get_providers";
 	GList *list = NULL;
-	GList *ip;
 
 	g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
 	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
 
 	if( !pivot->private->dispose_has_run ){
 
-		for( ip = pivot->private->providers ; ip ; ip = ip->next ){
-			if( G_TYPE_CHECK_INSTANCE_TYPE( G_OBJECT( ip->data ), type )){
-				list = g_list_prepend( list, g_object_ref( ip->data ));
-			}
-		}
+		list = na_module_get_extensions_for_type( pivot->private->modules, type );
+		g_debug( "%s: list=%p, count=%d", thisfn, ( void * ) list, list ? g_list_length( list ) : 0 );
 	}
 
 	return( list );
@@ -429,8 +410,7 @@ na_pivot_free_providers( GList *providers )
 
 	g_debug( "%s: providers=%p", thisfn, ( void * ) providers );
 
-	g_list_foreach( providers, ( GFunc ) g_object_unref, NULL );
-	g_list_free( providers );
+	na_module_free_extensions_list( providers );
 }
 
 /**
@@ -809,6 +789,7 @@ free_consumers( GList *consumers )
  * notification messages to this NAPivot, letting this later redirect
  * them to appropriate NAIPivotConsumers.
  */
+/*
 static void
 register_io_providers( NAPivot *pivot )
 {
@@ -822,7 +803,7 @@ register_io_providers( NAPivot *pivot )
 	list = g_list_prepend( list, na_gconf_provider_new( pivot ));
 
 	pivot->private->providers = list;
-}
+}*/
 
 /*
  * this handler is trigerred by IIOProviders when an action is changed
diff --git a/nautilus-actions/runtime/na-xml-writer.c b/nautilus-actions/runtime/na-xml-writer.c
index c6298d4..9abbd74 100644
--- a/nautilus-actions/runtime/na-xml-writer.c
+++ b/nautilus-actions/runtime/na-xml-writer.c
@@ -37,7 +37,8 @@
 
 #include <api/na-object-api.h>
 
-#include <runtime/na-gconf-provider-keys.h>
+#include <io-provider-gconf/nagp-keys.h>
+
 #include <runtime/na-iprefs.h>
 #include <runtime/na-utils.h>
 
diff --git a/nautilus-actions/utils/nautilus-actions-new.c b/nautilus-actions/utils/nautilus-actions-new.c
index de3832c..f2b2e9e 100644
--- a/nautilus-actions/utils/nautilus-actions-new.c
+++ b/nautilus-actions/utils/nautilus-actions-new.c
@@ -39,7 +39,8 @@
 #include <api/na-iio-provider.h>
 #include <api/na-object-api.h>
 
-#include <runtime/na-gconf-provider.h>
+#include <io-provider-gconf/nagp-keys.h>
+
 #include <runtime/na-io-provider.h>
 #include <runtime/na-iprefs.h>
 #include <runtime/na-utils.h>
@@ -368,7 +369,7 @@ get_action_from_cmdline( void )
 static gboolean
 write_to_gconf( NAObjectAction *action, GSList **msg )
 {
-	NAGConfProvider *gconf;
+	/*NAGConfProvider *gconf;
 	guint ret;
 
 	gconf = na_gconf_provider_new( NULL );
@@ -377,7 +378,8 @@ write_to_gconf( NAObjectAction *action, GSList **msg )
 
 	ret = na_io_provider_write_item( NULL, NA_OBJECT_ITEM( action ), msg );
 
-	return( ret == NA_IIO_PROVIDER_WRITE_OK );
+	return( ret == NA_IIO_PROVIDER_WRITE_OK );*/
+	return( TRUE );
 }
 
 /*



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