[nautilus-actions] Define libna-runtime convenience library



commit b99cfe0f3289df94645d3b9bc9caf173aa22880e
Author: Pierre Wieser <pwieser trychlos org>
Date:   Fri Oct 2 16:27:53 2009 +0200

    Define libna-runtime convenience library
    
    It centralizes classes and methods which are only shared by the Nautilus Actions plugin.
    This should help to keep the plugin as light and efficient as possible.

 ChangeLog                                          |   48 +
 configure.ac                                       |    1 +
 m4/na-log-domains.m4                               |    7 +-
 src/Makefile.am                                    |    1 +
 src/common/Makefile.am                             |   32 +-
 src/common/na-object-action.c                      |   68 -
 src/common/na-object-action.h                      |    8 -
 src/common/na-object-api.h                         |   29 -
 src/common/na-object-fn.h                          |    2 -
 src/common/na-object-id-fn.h                       |    1 -
 src/common/na-object-id.c                          |   79 -
 src/common/na-object-item-fn.h                     |   16 -
 src/common/na-object-item.c                        |  185 ---
 src/common/na-object-menu.h                        |    3 -
 src/common/na-object.c                             |   29 -
 src/common/na-utils.c                              |   89 --
 src/common/na-utils.h                              |    7 -
 src/nact/Makefile.am                               |    3 +-
 src/plugin/Makefile.am                             |    2 +-
 src/plugin/nautilus-actions.c                      |   22 +-
 src/plugin/nautilus-module.c                       |    2 +-
 src/runtime/Makefile.am                            |   84 +
 .../na-gconf-keys.h}                               |   18 +-
 src/{common => runtime}/na-gconf-monitor.c         |    0
 src/{common => runtime}/na-gconf-monitor.h         |    4 +-
 src/{common => runtime}/na-gconf-provider-keys.h   |    3 +-
 src/{common => runtime}/na-gconf-provider.c        |   23 +-
 src/{common => runtime}/na-gconf-provider.h        |    4 +-
 src/{common => runtime}/na-gconf-utils.c           |    0
 src/{common => runtime}/na-gconf-utils.h           |    2 +-
 src/{common => runtime}/na-gnome-vfs-uri.c         |    0
 src/{common => runtime}/na-gnome-vfs-uri.h         |    0
 src/{common => runtime}/na-iabout.c                |    0
 src/{common => runtime}/na-iabout.h                |    5 +-
 src/{common => runtime}/na-iduplicable.c           |    0
 src/{common => runtime}/na-iduplicable.h           |    2 +-
 src/{common => runtime}/na-iio-provider.c          |    4 +-
 src/{common => runtime}/na-iio-provider.h          |    8 +-
 src/{common => runtime}/na-ipivot-consumer.c       |    2 +-
 src/{common => runtime}/na-ipivot-consumer.h       |    2 +-
 src/runtime/na-iprefs.c                            |  413 +++++
 src/runtime/na-iprefs.h                            |  125 ++
 src/{common => runtime}/na-object-action-class.h   |    5 +-
 .../na-object-action-fn.h}                         |   41 +-
 src/runtime/na-object-action.c                     |  585 +++++++
 src/runtime/na-object-api.h                        |   96 ++
 src/{common => runtime}/na-object-class.h          |   28 +-
 .../na-object-fn.h}                                |   40 +-
 src/{common => runtime}/na-object-id-class.h       |    9 +-
 .../na-object-id-fn.h}                             |   33 +-
 src/runtime/na-object-id.c                         |  518 +++++++
 src/{common => runtime}/na-object-item-class.h     |    2 +-
 src/runtime/na-object-item-fn.h                    |   69 +
 src/runtime/na-object-item.c                       |  910 +++++++++++
 src/runtime/na-object-menu-class.h                 |   73 +
 .../na-object-menu-fn.h}                           |   32 +-
 src/runtime/na-object-menu.c                       |  362 +++++
 src/{common => runtime}/na-object-profile-class.h  |    2 +-
 src/runtime/na-object-profile-fn.h                 |   86 ++
 src/runtime/na-object-profile.c                    | 1601 ++++++++++++++++++++
 src/runtime/na-object.c                            |  662 ++++++++
 src/{common => runtime}/na-pivot.c                 |    5 +-
 src/{common => runtime}/na-pivot.h                 |    0
 src/runtime/na-utils.c                             |  182 +++
 .../na-gconf-keys-schemas.h => runtime/na-utils.h} |   27 +-
 src/test/Makefile.am                               |    4 +-
 src/utils/Makefile.am                              |    6 +-
 67 files changed, 6037 insertions(+), 674 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 05475c8..11d48bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,53 @@
 2009-10-02 Pierre Wieser <pwieser trychlos org>
 
+	Centralize plugin routines in a dedicated libna-runtime library.
+
+	* configure.ac: Add src/runtime/Makefile generation.
+
+	* m4/na-log-domains.m4: Define NA-runtime log domain.
+
+	* src/Makefile.am: Recurse into runtime subdirectory.
+
+	* src/common/na-gconf-keys-base.h:
+	* src/common/na-gconf-keys-schemas.h:
+	* src/common/na-gconf-monitor.c:
+	* src/common/na-gconf-monitor.h:
+	* src/common/na-gconf-provider-keys.h:
+	* src/common/na-gconf-provider.c:
+	* src/common/na-gconf-provider.h:
+	* src/common/na-gconf-utils.c:
+	* src/common/na-gconf-utils.h:
+	* src/common/na-gnome-vfs-uri.c:
+	* src/common/na-gnome-vfs-uri.h:
+	* src/common/na-iabout.c:
+	* src/common/na-iabout.h:
+	* src/common/na-iduplicable.c:
+	* src/common/na-iduplicable.h:
+	* src/common/na-iio-provider.c:
+	* src/common/na-iio-provider.h:
+	* src/common/na-ipivot-consumer.c:
+	* src/common/na-ipivot-consumer.h:
+	* src/common/na-object-action-class.h:
+	* src/common/na-object-class.h:
+	* src/common/na-object-id-class.h:
+	* src/common/na-object-item-class.h:
+	* src/common/na-object-profile-class.h:
+	* src/common/na-pivot.c:
+	* src/common/na-pivot.h: Moved to libna-runtime library.
+
+	* src/common/na-object-action.c:
+	* src/common/na-object-action.h:
+	* src/common/na-object-menu.c:
+	* src/common/na-object-menu.h:
+	* src/common/na-object-profile.c:
+	* src/common/na-object-profile.h: Remove runtime functions.
+
+	* src/common/Makefile.am: Updated accordingly.
+
+	* src/runtime/Makefile.am: New file.
+
+2009-10-02 Pierre Wieser <pwieser trychlos org>
+
 	* src/nact/base-application.c:
 	* src/nact/base-application.h (base_application_message_dlg):
 	New function.
diff --git a/configure.ac b/configure.ac
index cd60585..de2a35f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,6 +51,7 @@ AC_CONFIG_FILES([
 	src/common/Makefile
 	src/nact/Makefile
 	src/plugin/Makefile
+	src/runtime/Makefile
 	src/test/Makefile
 	src/utils/Makefile
 	po/Makefile.in
diff --git a/m4/na-log-domains.m4 b/m4/na-log-domains.m4
index 43e03dd..b811e99 100644
--- a/m4/na-log-domains.m4
+++ b/m4/na-log-domains.m4
@@ -2,11 +2,14 @@ dnl define three distinct log domains, respectively for common code,
 dnl plugin and NACT user interface - log handlers will be disabled
 dnl when not in development mode
 
-# serial 1 creation
+# serial 2 define NA-runtime log domain
 
 AC_DEFUN([NA_LOG_DOMAINS],[
+	AC_SUBST([NA_LOGDOMAIN_RUNTIME],[NA-runtime])
+	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_RUNTIME],["NA-runtime"],[Log domain of runtime library])
+
 	AC_SUBST([NA_LOGDOMAIN_COMMON],[NA-common])
-	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_COMMON],["NA-common"],[Log domain of common code])
+	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_COMMON],["NA-common"],[Log domain of common library])
 
 	AC_SUBST([NA_LOGDOMAIN_PLUGIN],[NA-plugin])
 	AC_DEFINE_UNQUOTED([NA_LOGDOMAIN_PLUGIN],["NA-plugin"],[Log domain of Nautilus plugin])
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e2cf1c..e027299 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,6 +28,7 @@
 
 SUBDIRS = \
 	common						\
+	runtime						\
 	nact						\
 	plugin						\
 	test						\
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 382a81a..a5ba239 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -26,7 +26,7 @@
 #   Pierre Wieser <pwieser trychlos org>
 #   ... and many others (see AUTHORS)
 
-noinst_LTLIBRARIES = libnact.la
+noinst_LTLIBRARIES = libna-common.la
 
 AM_CPPFLAGS += \
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
@@ -34,48 +34,22 @@ AM_CPPFLAGS += \
 	$(NAUTILUS_ACTIONS_CFLAGS)					\
 	$(NULL)
 
-libnact_la_SOURCES = \
-	na-gconf-keys-base.h						\
-	na-gconf-keys-schemas.h						\
-	na-gconf-monitor.c							\
-	na-gconf-monitor.h							\
-	na-gconf-provider.c							\
-	na-gconf-provider.h							\
-	na-gconf-provider-keys.h					\
-	na-gconf-utils.c							\
-	na-gconf-utils.h							\
-	na-gnome-vfs-uri.c							\
-	na-gnome-vfs-uri.h							\
-	na-iabout.c									\
-	na-iabout.h									\
-	na-iduplicable.c							\
-	na-iduplicable.h							\
-	na-iio-provider.c							\
-	na-iio-provider.h							\
-	na-ipivot-consumer.c						\
-	na-ipivot-consumer.h						\
+libna_common_la_SOURCES = \
 	na-iprefs.c									\
 	na-iprefs.h									\
 	na-object.c									\
 	na-object-api.h								\
-	na-object-class.h							\
 	na-object-fn.h								\
 	na-object-id.c								\
-	na-object-id-class.h						\
 	na-object-id-fn.h							\
 	na-object-item.c							\
-	na-object-item-class.h						\
 	na-object-item-fn.h							\
 	na-object-action.c							\
 	na-object-action.h							\
-	na-object-action-class.h					\
 	na-object-menu.c							\
 	na-object-menu.h							\
 	na-object-profile.c							\
 	na-object-profile.h							\
-	na-object-profile-class.h					\
-	na-pivot.c									\
-	na-pivot.h									\
 	na-utils.c									\
 	na-utils.h									\
 	na-xml-names.h								\
@@ -83,7 +57,7 @@ libnact_la_SOURCES = \
 	na-xml-writer.h								\
 	$(NULL)
 
-libnact_la_LIBADD = \
+libna_common_la_LIBADD = \
 	-lxml2										\
 	-luuid										\
 	$(NULL)
diff --git a/src/common/na-object-action.c b/src/common/na-object-action.c
index 8360d31..c402bff 100644
--- a/src/common/na-object-action.c
+++ b/src/common/na-object-action.c
@@ -334,32 +334,6 @@ na_object_action_new_with_profile( void )
 }
 
 /**
- * na_object_action_get_version:
- * @action: the #NAObjectAction object to be requested.
- *
- * Returns the version of the description of the action, as found when
- * reading it from the I/O storage subsystem.
- *
- * Returns: the version of the action as a newly allocated string. This
- * returned string must be g_free() by the caller.
- *
- * See na_object_set_version() for some rationale about version.
- */
-gchar *
-na_object_action_get_version( const NAObjectAction *action )
-{
-	gchar *version = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), NULL );
-
-	if( !action->private->dispose_has_run ){
-		g_object_get( G_OBJECT( action ), NAACTION_PROP_VERSION, &version, NULL );
-	}
-
-	return( version );
-}
-
-/**
  * na_object_action_is_readonly:
  * @action: the #NAObjectAction object to be requested.
  *
@@ -429,48 +403,6 @@ na_object_action_set_readonly( NAObjectAction *action, gboolean readonly )
 }
 
 /**
- * na_object_action_get_new_profile_name:
- * @action: the #NAObjectAction object which will receive a new profile.
- *
- * Returns a name suitable as a new profile name.
- *
- * The search is made by iterating over the standard profile name
- * prefix : basically, we increment a counter until finding a unique
- * name. The provided name is so only suitable for the specified
- * @action.
- *
- * Returns: a newly allocated profile name, which should be g_free() by
- * the caller.
- */
-gchar *
-na_object_action_get_new_profile_name( const NAObjectAction *action )
-{
-	int i;
-	gboolean ok = FALSE;
-	gchar *candidate = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), NULL );
-
-	if( !action->private->dispose_has_run ){
-
-		for( i=1 ; !ok ; ++i ){
-			g_free( candidate );
-			candidate = g_strdup_printf( "%s%d", OBJECT_PROFILE_PREFIX, i );
-			if( !na_object_get_item( action, candidate )){
-				ok = TRUE;
-			}
-		}
-
-		if( !ok ){
-			g_free( candidate );
-			candidate = NULL;
-		}
-	}
-
-	return( candidate );
-}
-
-/**
  * na_object_action_attach_profile:
  * @action: the #NAObjectAction action to which the profile will be attached.
  * @profile: the #NAObjectProfile profile to be attached to @action.
diff --git a/src/common/na-object-action.h b/src/common/na-object-action.h
index c80b66e..8ea7e5a 100644
--- a/src/common/na-object-action.h
+++ b/src/common/na-object-action.h
@@ -44,22 +44,14 @@
 
 G_BEGIN_DECLS
 
-/* i18n: default label for a newly created action */
-#define NA_OBJECT_ACTION_DEFAULT_LABEL		_( "New Nautilus action" )
-
-/* i18n: default label for a newly created profile */
-#define NA_OBJECT_PROFILE_DEFAULT_LABEL		_( "New profile" )
-
 NAObjectAction *na_object_action_new( void );
 NAObjectAction *na_object_action_new_with_profile( void );
 
-gchar          *na_object_action_get_version( const NAObjectAction *action );
 gboolean        na_object_action_is_readonly( const NAObjectAction *action );
 
 void            na_object_action_set_version( NAObjectAction *action, const gchar *version );
 void            na_object_action_set_readonly( NAObjectAction *action, gboolean readonly );
 
-gchar          *na_object_action_get_new_profile_name( const NAObjectAction *action );
 void            na_object_action_attach_profile( NAObjectAction *action, NAObjectProfile *profile );
 
 G_END_DECLS
diff --git a/src/common/na-object-api.h b/src/common/na-object-api.h
index e87703c..82226bb 100644
--- a/src/common/na-object-api.h
+++ b/src/common/na-object-api.h
@@ -45,17 +45,10 @@ G_BEGIN_DECLS
 
 /* NAObject
  */
-#define na_object_dump( object )					na_object_object_dump( NA_OBJECT( object ))
-#define na_object_dump_norec( object )				na_object_object_dump_norec( NA_OBJECT( object ))
-#define na_object_dump_tree( tree )					na_object_object_dump_tree( tree )
-#define na_object_get_clipboard_id( object )		na_object_object_get_clipboard_id( NA_OBJECT( object ))
-#define na_object_ref( object )						na_object_object_ref( NA_OBJECT( object ))
 
 /* NAIDuplicable
  */
-#define na_object_duplicate( object )				na_object_iduplicable_duplicate( NA_OBJECT( object ))
 #define na_object_check_edition_status( object )	na_object_iduplicable_check_edition_status( NA_OBJECT( object ))
-#define na_object_is_modified( object )				na_object_iduplicable_is_modified( NA_OBJECT( object ))
 #define na_object_is_valid( object )				na_object_iduplicable_is_valid( NA_OBJECT( object ))
 
 #define na_object_get_origin( object )				na_object_iduplicable_get_origin( NA_OBJECT( object ))
@@ -64,33 +57,11 @@ G_BEGIN_DECLS
 
 /* NAObjectId
  */
-#define na_object_get_id( object )					na_object_id_get_id( NA_OBJECT_ID( object ))
-#define na_object_get_label( object )				na_object_id_get_label( NA_OBJECT_ID( object ))
-
-#define na_object_set_id( object, id )				na_object_id_set_id( NA_OBJECT_ID( object ), id )
 #define na_object_set_for_copy( object, relabel )	na_object_id_set_for_copy( NA_OBJECT_ID( object ), relabel )
-#define na_object_set_new_id( object )				na_object_id_set_new_id( NA_OBJECT_ID( object ))
-#define na_object_set_label( object, label )		na_object_id_set_label( NA_OBJECT_ID( object ), label )
 
 /* NAObjectItem
  */
-#define na_object_get_tooltip( object )				na_object_item_get_tooltip( NA_OBJECT_ITEM( object ))
-#define na_object_get_icon( object )				na_object_item_get_icon( NA_OBJECT_ITEM( object ))
-#define na_object_get_pixbuf( object )				na_object_item_get_pixbuf( NA_OBJECT_ITEM( object ))
-#define na_object_get_provider( object )			na_object_item_get_provider( NA_OBJECT_ITEM( object ))
-#define na_object_is_enabled( object )				na_object_item_is_enabled( NA_OBJECT_ITEM( object ))
-#define na_object_get_item( object, id )			na_object_item_get_item( NA_OBJECT_ITEM( object ), id )
-#define na_object_get_items( object )				na_object_item_get_items( NA_OBJECT_ITEM( object ))
-#define na_object_get_items_count( object )			na_object_item_get_items_count( NA_OBJECT_ITEM( object ))
-#define na_object_free_items( list )				na_object_item_free_items( list )
-
-#define na_object_set_tooltip( object, tooltip )	na_object_item_set_tooltip( NA_OBJECT_ITEM( object ), tooltip )
-#define na_object_set_icon( object, icon )			na_object_item_set_icon( NA_OBJECT_ITEM( object ), icon )
-#define na_object_set_provider( object, provider )	na_object_item_set_provider( NA_OBJECT_ITEM( object ), provider )
-#define na_object_set_enabled( object, enabled )	na_object_item_set_enabled( NA_OBJECT_ITEM( object ), enabled )
-#define na_object_set_items( object, list )			na_object_item_set_items( NA_OBJECT_ITEM( object ), list )
 
-#define na_object_append_item( object, item )		na_object_item_append_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
 #define na_object_insert_item( object, item, before ) na_object_item_insert_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ), NA_OBJECT( before ))
 #define na_object_remove_item( object, item )		na_object_item_remove_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
 
diff --git a/src/common/na-object-fn.h b/src/common/na-object-fn.h
index 94c6fdf..8c5927f 100644
--- a/src/common/na-object-fn.h
+++ b/src/common/na-object-fn.h
@@ -49,10 +49,8 @@ G_BEGIN_DECLS
 /* NAIDuplicable
  */
 void      na_object_iduplicable_check_edition_status( const NAObject *object );
-NAObject *na_object_iduplicable_duplicate( const NAObject *object );
 
 gboolean  na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b );
-gboolean  na_object_iduplicable_is_modified( const NAObject *object );
 gboolean  na_object_iduplicable_is_valid( const NAObject *object );
 NAObject *na_object_iduplicable_get_origin( const NAObject *object );
 void      na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin );
diff --git a/src/common/na-object-id-fn.h b/src/common/na-object-id-fn.h
index 414f1a2..19ad8a4 100644
--- a/src/common/na-object-id-fn.h
+++ b/src/common/na-object-id-fn.h
@@ -51,7 +51,6 @@ gchar *na_object_id_get_label( const NAObjectId *object );
 
 void   na_object_id_set_id( NAObjectId *object, const gchar *id );
 void   na_object_id_set_for_copy( NAObjectId *object, gboolean relabel );
-void   na_object_id_set_new_id( NAObjectId *object );
 void   na_object_id_set_label( NAObjectId *object, const gchar *label );
 
 G_END_DECLS
diff --git a/src/common/na-object-id.c b/src/common/na-object-id.c
index a6977b1..8ee2501 100644
--- a/src/common/na-object-id.c
+++ b/src/common/na-object-id.c
@@ -82,9 +82,6 @@ static void     object_copy( NAObject *target, const NAObject *source );
 static gboolean object_are_equal( const NAObject *a, const NAObject *b );
 static gboolean object_is_valid( const NAObject *object );
 
-static gchar   *v_new_id( NAObjectId *object );
-static gchar   *most_derived_new_id( NAObjectId *object );
-
 GType
 na_object_id_get_type( void )
 {
@@ -372,48 +369,6 @@ na_object_id_set_for_copy( NAObjectId *object, gboolean relabel )
 	}
 }
 
-/**
- * na_object_id_set_new_id:
- * @object: the #NAObjectId object whose internal identifiant is to be
- * set.
- *
- * Request a new id to the derived class, and set it.
- */
-void
-na_object_id_set_new_id( NAObjectId *object )
-{
-	gchar *id;
-
-	g_return_if_fail( NA_IS_OBJECT_ID( object ));
-
-	if( !object->private->dispose_has_run ){
-
-		id = v_new_id( object );
-
-		if( id ){
-			g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_ID, id, NULL );
-			g_free( id );
-		}
-	}
-}
-
-/**
- * na_object_id_set_label:
- * @object: the #NAObjectId object whose label is to be set.
- * @label: label to be set.
- *
- * Sets the label of @object by taking a copy of the provided one.
- */
-void
-na_object_id_set_label( NAObjectId *object, const gchar *label )
-{
-	g_return_if_fail( NA_IS_OBJECT_ID( object ));
-
-	if( !object->private->dispose_has_run ){
-		g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_LABEL, label, NULL );
-	}
-}
-
 static void
 object_dump( const NAObject *object )
 {
@@ -510,37 +465,3 @@ object_is_valid( const NAObject *object )
 
 	return( valid );
 }
-
-static gchar *
-v_new_id( NAObjectId *object )
-{
-	return( most_derived_new_id( object ));
-}
-
-static gchar *
-most_derived_new_id( NAObjectId *object )
-{
-	gchar *new_id;
-	GList *hierarchy, *ih;
-	gboolean found;
-
-	found = FALSE;
-	new_id = NULL;
-	hierarchy = g_list_reverse( na_object_get_hierarchy( NA_OBJECT( object )));
-	/*g_debug( "na_object_id_most_derived_id: object=%p (%s)",
-					( void * ) object, G_OBJECT_TYPE_NAME( object ));*/
-
-	for( ih = hierarchy ; ih && !found ; ih = ih->next ){
-		if( NA_OBJECT_ID_CLASS( ih->data )->new_id ){
-			new_id = NA_OBJECT_ID_CLASS( ih->data )->new_id( object );
-			found = TRUE;
-		}
-		if( G_OBJECT_CLASS_TYPE( ih->data ) == NA_OBJECT_ID_TYPE ){
-			break;
-		}
-	}
-
-	na_object_free_hierarchy( hierarchy );
-
-	return( new_id );
-}
diff --git a/src/common/na-object-item-fn.h b/src/common/na-object-item-fn.h
index 349128a..5d7bce3 100644
--- a/src/common/na-object-item-fn.h
+++ b/src/common/na-object-item-fn.h
@@ -49,24 +49,8 @@
 
 G_BEGIN_DECLS
 
-gchar         *na_object_item_get_tooltip( const NAObjectItem *item );
-gchar         *na_object_item_get_icon( const NAObjectItem *item );
-gchar         *na_object_item_get_verified_icon_name( const NAObjectItem *item );
 GdkPixbuf     *na_object_item_get_pixbuf( const NAObjectItem *item, GtkWidget *widget );
-gboolean       na_object_item_is_enabled( const NAObjectItem *item );
-NAIIOProvider *na_object_item_get_provider( const NAObjectItem *item );
-NAObject      *na_object_item_get_item( const NAObjectItem *item, const gchar *id );
-GList         *na_object_item_get_items( const NAObjectItem *item );
-guint          na_object_item_get_items_count( const NAObjectItem *item );
-void           na_object_item_free_items( GList *items );
 
-void           na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip );
-void           na_object_item_set_icon( NAObjectItem *item, const gchar *icon_name );
-void           na_object_item_set_enabled( NAObjectItem *item, gboolean enabled );
-void           na_object_item_set_provider( NAObjectItem *item, const NAIIOProvider *provider );
-void           na_object_item_set_items( NAObjectItem *item, GList *items );
-
-void           na_object_item_append_item( NAObjectItem *item, const NAObject *object );
 void           na_object_item_insert_item( NAObjectItem *item, const NAObject *object, const NAObject *before );
 void           na_object_item_remove_item( NAObjectItem *item, const NAObject *object );
 
diff --git a/src/common/na-object-item.c b/src/common/na-object-item.c
index c9612d6..a72daf7 100644
--- a/src/common/na-object-item.c
+++ b/src/common/na-object-item.c
@@ -336,54 +336,6 @@ instance_finalize( GObject *object )
 	}
 }
 
-/**
- * na_object_item_get_tooltip:
- * @item: the #NAObjectItem object to be requested.
- *
- * Returns the tooltip which will be display in the Nautilus context
- * menu item for this @item.
- *
- * Returns: the tooltip of the @item as a newly allocated string. This
- * returned string must be g_free() by the caller.
- */
-gchar *
-na_object_item_get_tooltip( const NAObjectItem *item )
-{
-	gchar *tooltip = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
-
-	if( !item->private->dispose_has_run ){
-		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_TOOLTIP, &tooltip, NULL );
-	}
-
-	return( tooltip );
-}
-
-/**
- * na_object_item_get_icon:
- * @item: the #NAObjectItem object to be requested.
- *
- * Returns the name of the icon attached to the Nautilus context menu
- * item for this @item.
- *
- * Returns: the icon name as a newly allocated string. This returned
- * string must be g_free() by the caller.
- */
-gchar *
-na_object_item_get_icon( const NAObjectItem *item )
-{
-	gchar *icon = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
-
-	if( !item->private->dispose_has_run ){
-		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ICON, &icon, NULL );
-	}
-
-	return( icon );
-}
-
 /*
  * TODO: remove this function
  */
@@ -462,143 +414,6 @@ GdkPixbuf *na_object_item_get_pixbuf( const NAObjectItem *item, GtkWidget *widge
 }
 
 /**
- * na_object_item_get_provider:
- * @item: the #NAObjectItem object to be requested.
- *
- * Returns the initial provider of the item (or the last which has
- * accepted a write operation). At the time of this request, this is
- * the most probable provider willing to accept a next writing
- * operation.
- *
- * Returns: a #NAIIOProvider object. The reference is
- * owned by #NAPivot pivot and should not be g_object_unref() by the
- * caller.
- */
-NAIIOProvider *
-na_object_item_get_provider( const NAObjectItem *item )
-{
-	NAIIOProvider *provider = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
-
-	if( !item->private->dispose_has_run ){
-		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_PROVIDER, &provider, NULL );
-	}
-
-	return( provider );
-}
-
-/**
- * na_object_item_get_item:
- * @item: the #NAObjectItem from which we want retrieve a subitem.
- * @id: the id of the searched subitem.
- *
- * Returns: a pointer to the #NAObject subitem with the required id.
- *
- * The returned #NAObject is owned by the @item object ; the
- * caller should not try to g_free() nor g_object_unref() it.
- */
-NAObject *
-na_object_item_get_item( const NAObjectItem *item, const gchar *id )
-{
-	GList *it;
-	NAObject *found = NULL;
-	NAObject *isub;
-	gchar *isubid;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
-
-	if( !item->private->dispose_has_run ){
-
-		for( it = item->private->items ; it && !found ; it = it->next ){
-			isub = NA_OBJECT( it->data );
-			isubid = na_object_get_id( isub );
-			if( !strcmp( id, isubid )){
-				found = isub;
-			}
-			g_free( isubid );
-		}
-	}
-
-	return( found );
-}
-
-/**
- * na_object_item_get_items:
- * @item: the #NAObjectItem from which we want a list of subitems.
- *
- * Returns: a newly allocated #GList of #NAObject objects which are
- * embedded in the @item. Depending of the exact nature of @item, these
- * may be #NAObjectMenu, #NAObjectAction or #NAObjectProfile subitems.
- *
- * The returned pointer should be na_object_item_free_items() or
- * na_object_free_items() by the caller.
- */
-GList *
-na_object_item_get_items( const NAObjectItem *item )
-{
-	GList *items = NULL;
-	GList *it;
-
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
-
-	if( !item->private->dispose_has_run ){
-
-		for( it = item->private->items ; it ; it = it->next ){
-			items = g_list_prepend( items, g_object_ref( it->data ));
-		}
-
-		items = g_list_reverse( items );
-	}
-
-	return( items );
-}
-
-/**
- * na_object_item_get_items_count:
- * @item: the #NAObjectItem from which we want a count of subitems.
- *
- * Returns: the count of subitems of @item.
- */
-guint
-na_object_item_get_items_count( const NAObjectItem *item )
-{
-	guint count = 0;
-
-	/*g_debug( "na_object_item_get_items_count: item=%p (%s)", ( void * ) item, G_OBJECT_TYPE_NAME( item ));*/
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), 0 );
-
-	if( !item->private->dispose_has_run ){
-		count = item->private->items ? g_list_length( item->private->items ) : 0;
-	}
-
-	return( count );
-}
-
-/**
- * na_object_item_free_items:
- * @list: a list of #NAObject subitems as returned by
- * na_object_item_get_items().
- *
- * Frees the list.
- */
-void
-na_object_item_free_items( GList *items )
-{
-	GList *it;
-
-	for( it = items ; it ; it = it->next ){
-		if( G_IS_OBJECT( it->data )){
-			g_object_unref( it->data );
-		/*} else {
-			g_warning( "na_object_item_free_items: %p not an object", ( void * ) it->data );*/
-		}
-	}
-
-	g_list_free( items );
-}
-
-/**
  * na_object_item_is_enabled:
  * @item: the #NAObjectItem object to be requested.
  *
diff --git a/src/common/na-object-menu.h b/src/common/na-object-menu.h
index 656f8d7..0b5becf 100644
--- a/src/common/na-object-menu.h
+++ b/src/common/na-object-menu.h
@@ -66,9 +66,6 @@ typedef struct {
 }
 	NAObjectMenuClass;
 
-/* i18n: default label for a newly created menu */
-#define NA_OBJECT_MENU_DEFAULT_LABEL	_( "New Nautilus menu" )
-
 GType         na_object_menu_get_type( void );
 
 NAObjectMenu *na_object_menu_new( void );
diff --git a/src/common/na-object.c b/src/common/na-object.c
index ac6ceda..d06f825 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -358,35 +358,6 @@ na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b )
 }
 
 /**
- * na_object_iduplicable_is_modified:
- * @object: the #NAObject object whose status is requested.
- *
- * Returns the current modification status of @object.
- *
- * This suppose that @object has been previously duplicated in order
- * to get benefits provided by the IDuplicable interface.
- *
- * This suppose also that the edition status of @object has previously
- * been checked via na_object_check_edited_status().
- *
- * Returns: %TRUE is the provided object has been modified regarding to
- * the original one, %FALSE else.
- */
-gboolean
-na_object_iduplicable_is_modified( const NAObject *object )
-{
-	gboolean is_modified = FALSE;
-
-	g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
-
-	if( !object->private->dispose_has_run ){
-		is_modified = na_iduplicable_is_modified( NA_IDUPLICABLE( object ));
-	}
-
-	return( is_modified );
-}
-
-/**
  * na_object_iduplicable_is_valid:
  * @object: the #NAObject object whose validity is to be checked.
  *
diff --git a/src/common/na-utils.c b/src/common/na-utils.c
index f54bfef..cd6fe7f 100644
--- a/src/common/na-utils.c
+++ b/src/common/na-utils.c
@@ -41,61 +41,6 @@
 static GSList *text_to_string_list( const gchar *text, const gchar *separator, const gchar *default_value );
 
 /**
- * na_utils_find_in_list:
- * @list: the GSList of strings to be searched.
- * @str: the searched string.
- *
- * Search for a string in a string list.
- *
- * Returns: %TRUE if the string has been found in list.
- */
-gboolean
-na_utils_find_in_list( GSList *list, const gchar *str )
-{
-	GSList *il;
-
-	for( il = list ; il ; il = il->next ){
-		const gchar *istr = ( const gchar * ) il->data;
-		if( !g_utf8_collate( str, istr )){
-			return( TRUE );
-		}
-	}
-
-	return( FALSE );
-}
-
-/**
- * na_utils_string_lists_are_equal:
- * @first: a GSList of strings.
- * @second: another GSList of strings to be compared with @first.
- *
- * Compare two string lists, without regards to the order.
- *
- * Returns: %TRUE if the two lists have same content.
- */
-gboolean
-na_utils_string_lists_are_equal( GSList *first, GSList *second )
-{
-	GSList *il;
-
-	for( il = first ; il ; il = il->next ){
-		const gchar *str = ( const gchar * ) il->data;
-		if( !na_utils_find_in_list( second, str )){
-			return( FALSE );
-		}
-	}
-
-	for( il = second ; il ; il = il->next ){
-		const gchar *str = ( const gchar * ) il->data;
-		if( !na_utils_find_in_list( first, str )){
-			return( FALSE );
-		}
-	}
-
-	return( TRUE );
-}
-
-/**
  * na_utils_duplicate_string_list:
  * @list: the GSList to be duplicated.
  *
@@ -267,40 +212,6 @@ na_utils_dump_string_list( GSList *list )
 }
 
 /**
- * na_utils_gslist_to_schema:
- * @list: a list of strings.
- *
- * Converts a list of strings to a comma-separated list of strings,
- * enclosed by brackets (dump format, GConf export format).
- *
- * Returns: a newly allocated string which should be g_free() by the caller.
- */
-gchar *
-na_utils_gslist_to_schema( GSList *list )
-{
-	GSList *ib;
-	gchar *tmp;
-	gchar *text = g_strdup( "" );
-
-	for( ib = list ; ib ; ib = ib->next ){
-		if( strlen( text )){
-			tmp = g_strdup_printf( "%s,", text );
-			g_free( text );
-			text = tmp;
-		}
-		tmp = g_strdup_printf( "%s%s", text, ( gchar * ) ib->data );
-		g_free( text );
-		text = tmp;
-	}
-
-	tmp = g_strdup_printf( "[%s]", text );
-	g_free( text );
-	text = tmp;
-
-	return( text );
-}
-
-/**
  * na_utils_schema_to_gslist:
  * @value: a string of the form [xxx,yyy,...] as read from GConf.
  *
diff --git a/src/common/na-utils.h b/src/common/na-utils.h
index eecb1ac..9b6afa3 100644
--- a/src/common/na-utils.h
+++ b/src/common/na-utils.h
@@ -38,23 +38,16 @@ G_BEGIN_DECLS
 /*
  * Some functions to ease the GSList list manipulations.
  */
-gboolean na_utils_find_in_list( GSList *list, const gchar *str );
-gboolean na_utils_string_lists_are_equal( GSList *first, GSList *second );
-GSList  *na_utils_duplicate_string_list( GSList *list );
 GSList  *na_utils_remove_ascii_from_string_list( GSList *list, const gchar *text );
-void     na_utils_free_string_list( GSList *list );
 gchar   *na_utils_string_list_to_text( GSList *list );
 GSList  *na_utils_text_to_string_list( const gchar *text );
 GSList  *na_utils_lines_to_string_list( const gchar *text );
 void     na_utils_dump_string_list( GSList *list );
 
-gchar   *na_utils_gslist_to_schema( GSList *list );
 GSList  *na_utils_schema_to_gslist( const gchar *value );
 gchar   *na_utils_boolean_to_schema( gboolean b );
 gboolean na_utils_schema_to_boolean( const gchar *value, gboolean default_value );
 
-gchar   *na_utils_path_extract_last_dir( const gchar *path );
-
 /*
  * Some functions for GString manipulations.
  */
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index cf4bdbb..8800c5f 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -92,7 +92,8 @@ nautilus_actions_config_tool_SOURCES = \
 	$(NULL)
 
 nautilus_actions_config_tool_LDADD = \
-	$(top_builddir)/src/common/libnact.la				\
+	$(top_builddir)/src/common/libna-common.la			\
+	$(top_builddir)/src/common/libna-runtime.la			\
 	$(NAUTILUS_ACTIONS_LIBS)							\
 	$(NULL)
 
diff --git a/src/plugin/Makefile.am b/src/plugin/Makefile.am
index 4d75b44..adf406d 100644
--- a/src/plugin/Makefile.am
+++ b/src/plugin/Makefile.am
@@ -45,6 +45,6 @@ libnautilus_actions_la_SOURCES = \
 libnautilus_actions_la_LDFLAGS = -module -avoid-version
 
 libnautilus_actions_la_LIBADD = \
-	$(top_builddir)/src/common/libnact.la				\
+	$(top_builddir)/src/runtime/libna-runtime.la		\
 	$(NAUTILUS_ACTIONS_LIBS)							\
 	$(NULL)
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index 83f5253..300cce9 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -38,14 +38,11 @@
 #include <libnautilus-extension/nautilus-file-info.h>
 #include <libnautilus-extension/nautilus-menu-provider.h>
 
-#include <common/na-object-api.h>
-#include <common/na-object-menu.h>
-#include <common/na-object-action.h>
-#include <common/na-object-profile.h>
-#include <common/na-pivot.h>
-#include <common/na-iabout.h>
-#include <common/na-iprefs.h>
-#include <common/na-ipivot-consumer.h>
+#include <runtime/na-object-api.h>
+#include <runtime/na-pivot.h>
+#include <runtime/na-iabout.h>
+#include <runtime/na-iprefs.h>
+#include <runtime/na-ipivot-consumer.h>
 
 #include "nautilus-actions.h"
 
@@ -211,7 +208,9 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private = g_new0( NautilusActionsPrivate, 1 );
 	self->private->dispose_has_run = FALSE;
 
-	/* from na-pivot */
+	/* initialize NAPivot and load actions through NAIIOProvider interface
+	 * forwarding notification messages from NAPivot to NautilusActions
+	 */
 	self->private->pivot = na_pivot_new( NA_IPIVOT_CONSUMER( self ));
 	na_pivot_set_automatic_reload( self->private->pivot, TRUE );
 }
@@ -309,6 +308,10 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
 
 	g_return_val_if_fail( NAUTILUS_IS_ACTIONS( provider ), NULL );
 	self = NAUTILUS_ACTIONS( provider );
+	if( !NA_IS_PIVOT( self->private->pivot )){
+		g_warning( "%s: NAPivot is null", thisfn );
+		g_return_val_if_fail( NA_IS_PIVOT( self->private->pivot ), NULL );
+	}
 
 	/* no need to go further if there is no files in the list */
 	if( !g_list_length( files )){
@@ -417,6 +420,7 @@ is_action_candidate( NautilusActions *plugin, NAObjectAction *action, GList *fil
  		}
  	}
 
+	na_object_free_items( profiles );
 	g_free( action_label );
 
 	return( candidate );
diff --git a/src/plugin/nautilus-module.c b/src/plugin/nautilus-module.c
index e73abe5..005e60d 100644
--- a/src/plugin/nautilus-module.c
+++ b/src/plugin/nautilus-module.c
@@ -64,7 +64,7 @@ nautilus_module_initialize( GTypeModule *module )
 	if( !st_log_handler ){
 		openlog( G_LOG_DOMAIN, LOG_PID, LOG_USER );
 		st_log_handler = g_log_set_handler( NA_LOGDOMAIN_PLUGIN, G_LOG_LEVEL_DEBUG, na_log_handler, NULL );
-		g_log_set_handler( NA_LOGDOMAIN_COMMON, G_LOG_LEVEL_DEBUG, na_log_handler, NULL );
+		g_log_set_handler( NA_LOGDOMAIN_RUNTIME, G_LOG_LEVEL_DEBUG, na_log_handler, NULL );
 	}
 
 	g_debug( "%s: module=%p", thisfn, ( void * ) module );
diff --git a/src/runtime/Makefile.am b/src/runtime/Makefile.am
new file mode 100644
index 0000000..243687b
--- /dev/null
+++ b/src/runtime/Makefile.am
@@ -0,0 +1,84 @@
+# 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)
+
+noinst_LTLIBRARIES = libna-runtime.la
+
+AM_CPPFLAGS += \
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
+	-DG_LOG_DOMAIN=\"${NA_LOGDOMAIN_RUNTIME}\"	\
+	$(NAUTILUS_ACTIONS_CFLAGS)					\
+	$(NULL)
+
+libna_runtime_la_SOURCES = \
+	na-gconf-keys.h								\
+	na-gconf-monitor.c							\
+	na-gconf-monitor.h							\
+	na-gconf-provider.c							\
+	na-gconf-provider.h							\
+	na-gconf-provider-keys.h					\
+	na-gconf-utils.c							\
+	na-gconf-utils.h							\
+	na-gnome-vfs-uri.c							\
+	na-gnome-vfs-uri.h							\
+	na-iabout.c									\
+	na-iabout.h									\
+	na-iduplicable.c							\
+	na-iduplicable.h							\
+	na-iio-provider.c							\
+	na-iio-provider.h							\
+	na-ipivot-consumer.c						\
+	na-ipivot-consumer.h						\
+	na-iprefs.c									\
+	na-iprefs.h									\
+	na-object-api.h								\
+	na-object.c									\
+	na-object-class.h							\
+	na-object-fn.h								\
+	na-object-id.c								\
+	na-object-id-class.h						\
+	na-object-id-fn.h							\
+	na-object-item.c							\
+	na-object-item-class.h						\
+	na-object-item-fn.h							\
+	na-object-action.c							\
+	na-object-action-class.h					\
+	na-object-action-fn.h						\
+	na-object-menu.c							\
+	na-object-menu-class.h						\
+	na-object-menu-fn.h							\
+	na-object-profile.c							\
+	na-object-profile-class.h					\
+	na-object-profile-fn.h						\
+	na-pivot.c									\
+	na-pivot.h									\
+	na-utils.c									\
+	na-utils.h									\
+	$(NULL)
+
+libna_runtime_la_LIBADD = \
+	$(NULL)
diff --git a/src/common/na-gconf-keys-base.h b/src/runtime/na-gconf-keys.h
similarity index 76%
copy from src/common/na-gconf-keys-base.h
copy to src/runtime/na-gconf-keys.h
index 5ebc0d8..f5a7158 100644
--- a/src/common/na-gconf-keys-base.h
+++ b/src/runtime/na-gconf-keys.h
@@ -28,16 +28,20 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_GCONF_KEYS_BASE_H__
-#define __NA_GCONF_KEYS_BASE_H__
+#ifndef __NA_GCONF_KEYS_H__
+#define __NA_GCONF_KEYS_H__
 
-/* GConf general information
+/**
+ * SECTION: na_gconf
+ * @short_description: GConf general information.
+ * @include: runtime/na-gconf-keys.h
  *
- * They are used both:
+ * These keys are used both:
  * - by GConf as a NAIIOProvider
  * - by GConf as the preferences storage system
- * - for providing schemas in import/export actions
+ * - as a part of schemas path in import/export operations
  */
-#define NAUTILUS_ACTIONS_GCONF_BASEDIR			"/apps/nautilus-actions"
+#define NAUTILUS_ACTIONS_GCONF_BASEDIR			"/apps/" PACKAGE
+#define NAUTILUS_ACTIONS_GCONF_SCHEMASDIR		"/schemas"
 
-#endif /* __NA_GCONF_KEYS_BASE_H__ */
+#endif /* __NA_GCONF_KEYS_H__ */
diff --git a/src/common/na-gconf-monitor.c b/src/runtime/na-gconf-monitor.c
similarity index 100%
rename from src/common/na-gconf-monitor.c
rename to src/runtime/na-gconf-monitor.c
diff --git a/src/common/na-gconf-monitor.h b/src/runtime/na-gconf-monitor.h
similarity index 95%
rename from src/common/na-gconf-monitor.h
rename to src/runtime/na-gconf-monitor.h
index b597f31..0663d2d 100644
--- a/src/common/na-gconf-monitor.h
+++ b/src/runtime/na-gconf-monitor.h
@@ -34,9 +34,11 @@
 /**
  * SECTION: na_gconf_monitor
  * @short_description: #NAGConfMonitor class definition.
- * @include: common/na-gconf-monitor.h
+ * @include: runtime/na-gconf-monitor.h
  *
  * This class manages the GConf monitoring.
+ * It is used to monitor both the GConf provider and the GConf runtime
+ * preferences.
  */
 
 #include <gconf/gconf-client.h>
diff --git a/src/common/na-gconf-provider-keys.h b/src/runtime/na-gconf-provider-keys.h
similarity index 97%
rename from src/common/na-gconf-provider-keys.h
rename to src/runtime/na-gconf-provider-keys.h
index 98e861f..d28f56e 100644
--- a/src/common/na-gconf-provider-keys.h
+++ b/src/runtime/na-gconf-provider-keys.h
@@ -31,8 +31,7 @@
 #ifndef __NA_GCONF_PROVIDER_KEYS_H__
 #define __NA_GCONF_PROVIDER_KEYS_H__
 
-#include "na-gconf-keys-base.h"
-#include "na-gconf-keys-schemas.h"
+#include "na-gconf-keys.h"
 
 /* GConf general information
  */
diff --git a/src/common/na-gconf-provider.c b/src/runtime/na-gconf-provider.c
similarity index 98%
rename from src/common/na-gconf-provider.c
rename to src/runtime/na-gconf-provider.c
index c1f87f5..5e12308 100644
--- a/src/common/na-gconf-provider.c
+++ b/src/runtime/na-gconf-provider.c
@@ -35,9 +35,6 @@
 #include <string.h>
 
 #include "na-object-api.h"
-#include "na-object-action.h"
-#include "na-object-profile.h"
-#include "na-object-menu.h"
 #include "na-gconf-monitor.h"
 #include "na-gconf-provider.h"
 #include "na-gconf-provider-keys.h"
@@ -475,26 +472,33 @@ read_item( NAGConfProvider *provider, const gchar *path )
 	gboolean have_items;
 	gboolean have_subdir;
 
+	/*g_debug( "%s: provider=%p, path=%s", thisfn, ( void * ) provider, path );*/
 	g_return_val_if_fail( NA_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 );
 
 	have_subdir = na_gconf_utils_have_subdir( provider->private->gconf, path );
 	have_items = na_gconf_utils_have_entry( provider->private->gconf, path, MENU_ITEMS_ENTRY );
+	/*g_debug( "%s: have_subdir=%s, have_items=%s", thisfn, have_subdir ? "True":"False", have_items ? "True":"False" );*/
 
 	if( have_subdir && have_items ){
-		g_warning( "%s: found both subdir and \"items\" entry at %s", thisfn, path );
+		g_warning( "%s: found both subdir(s) and \"items\" entry at %s", thisfn, path );
 		return( NULL );
 	}
 
+	/* it has a (maybe empty) 'items' entry: this is a menu
+	 */
 	if( have_items ){
 		item = NA_OBJECT_ITEM( na_object_menu_new());
 		read_item_menu( provider, path, NA_OBJECT_MENU( item ));
-		return( item );
+
+	/* else this should be an action
+	 */
+	} else {
+		item = NA_OBJECT_ITEM( na_object_action_new());
+		read_item_action( provider, path, NA_OBJECT_ACTION( item ));
 	}
 
-	item = NA_OBJECT_ITEM( na_object_action_new());
-	read_item_action( provider, path, NA_OBJECT_ACTION( item ));
 	return( item );
 }
 
@@ -609,13 +613,14 @@ read_item_action_profile( NAGConfProvider *provider, const gchar *path, NAObject
 static void
 read_item_action_profile_properties( NAGConfProvider *provider, GSList *entries, NAObjectProfile *profile )
 {
+	static const gchar *thisfn = "na_gconf_provider_read_item_action_profile_properties";
 	gchar *label, *path, *parameters;
 	GSList *basenames, *schemes, *mimetypes;
 	gboolean isfile, isdir, multiple, matchcase;
 
 	if( !na_gconf_utils_get_string_from_entries( entries, ACTION_PROFILE_LABEL_ENTRY, &label )){
-		/* i18n: default profile label */
-		label = g_strdup( NA_OBJECT_PROFILE_DEFAULT_LABEL );
+		g_warning( "%s: no label found", thisfn );
+		label = g_strdup( "" );
 	}
 	na_object_set_label( profile, label );
 	g_free( label );
diff --git a/src/common/na-gconf-provider.h b/src/runtime/na-gconf-provider.h
similarity index 96%
rename from src/common/na-gconf-provider.h
rename to src/runtime/na-gconf-provider.h
index 86b64a3..5bcfcc3 100644
--- a/src/common/na-gconf-provider.h
+++ b/src/runtime/na-gconf-provider.h
@@ -34,13 +34,13 @@
 /**
  * SECTION: na_gconf_provider
  * @short_description: #NAGConfProvider class definition.
- * @include: common/na-gconf-provider.h
+ * @include: runtime/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.
  *
- * #NAGConfProvider uses NAGConfMonitor to watch at the configuration
+ * #NAGConfProvider uses #NAGConfMonitor to watch at the configuration
  * tree. When something is modified, it sends the appropriate signal to
  * the #NAPivot object it was created against.
  */
diff --git a/src/common/na-gconf-utils.c b/src/runtime/na-gconf-utils.c
similarity index 100%
rename from src/common/na-gconf-utils.c
rename to src/runtime/na-gconf-utils.c
diff --git a/src/common/na-gconf-utils.h b/src/runtime/na-gconf-utils.h
similarity index 98%
rename from src/common/na-gconf-utils.h
rename to src/runtime/na-gconf-utils.h
index 2b55116..f5e1273 100644
--- a/src/common/na-gconf-utils.h
+++ b/src/runtime/na-gconf-utils.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_gconf_utils
  * @short_description: GConf utilities.
- * @include: common/na-gconf-utils.h
+ * @include: runtime/na-gconf-utils.h
  */
 
 #include <gconf/gconf.h>
diff --git a/src/common/na-gnome-vfs-uri.c b/src/runtime/na-gnome-vfs-uri.c
similarity index 100%
rename from src/common/na-gnome-vfs-uri.c
rename to src/runtime/na-gnome-vfs-uri.c
diff --git a/src/common/na-gnome-vfs-uri.h b/src/runtime/na-gnome-vfs-uri.h
similarity index 100%
rename from src/common/na-gnome-vfs-uri.h
rename to src/runtime/na-gnome-vfs-uri.h
diff --git a/src/common/na-iabout.c b/src/runtime/na-iabout.c
similarity index 100%
rename from src/common/na-iabout.c
rename to src/runtime/na-iabout.c
diff --git a/src/common/na-iabout.h b/src/runtime/na-iabout.h
similarity index 94%
rename from src/common/na-iabout.h
rename to src/runtime/na-iabout.h
index 0dda955..392724e 100644
--- a/src/common/na-iabout.h
+++ b/src/runtime/na-iabout.h
@@ -34,10 +34,11 @@
 /**
  * SECTION: na_iabout
  * @short_description: NAIAbout interface definition.
- * @include: common/na-iabout.h
+ * @include: runtime/na-iabout.h
  *
  * This interface displays the 'About Nautilus Actions' dialog box.
- * The application name may be provided by the implementor.
+ * The application name may be provided by the implementor ; else,
+ * the name of the application will be displayed.
  */
 
 #include <gtk/gtk.h>
diff --git a/src/common/na-iduplicable.c b/src/runtime/na-iduplicable.c
similarity index 100%
rename from src/common/na-iduplicable.c
rename to src/runtime/na-iduplicable.c
diff --git a/src/common/na-iduplicable.h b/src/runtime/na-iduplicable.h
similarity index 99%
rename from src/common/na-iduplicable.h
rename to src/runtime/na-iduplicable.h
index bc1345a..458025f 100644
--- a/src/common/na-iduplicable.h
+++ b/src/runtime/na-iduplicable.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_iduplicable
  * @short_description: #NAIDuplicable interface.
- * @include: common/na-iduplicable.h
+ * @include: runtime/na-iduplicable.h
  *
  * This interface is implemented by #NAObject in order to let
  * #NAObject-derived instance duplication be easily tracked. This works
diff --git a/src/common/na-iio-provider.c b/src/runtime/na-iio-provider.c
similarity index 99%
rename from src/common/na-iio-provider.c
rename to src/runtime/na-iio-provider.c
index c5d8f6e..5e2aed6 100644
--- a/src/common/na-iio-provider.c
+++ b/src/runtime/na-iio-provider.c
@@ -32,9 +32,9 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+
 #include "na-object-api.h"
-#include "na-object-action.h"
-#include "na-object-menu.h"
 #include "na-iio-provider.h"
 #include "na-iprefs.h"
 #include "na-utils.h"
diff --git a/src/common/na-iio-provider.h b/src/runtime/na-iio-provider.h
similarity index 96%
rename from src/common/na-iio-provider.h
rename to src/runtime/na-iio-provider.h
index c535243..a1ed571 100644
--- a/src/common/na-iio-provider.h
+++ b/src/runtime/na-iio-provider.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_iio_provider
  * @short_description: #NAIIOProvider interface definition.
- * @include: common/na-iio-provider.h
+ * @include: runtime/na-iio-provider.h
  *
  * This is the API all storage subsystems should implement in order to
  * provide I/O resources to NautilusActions.
@@ -62,12 +62,12 @@ typedef struct {
 	NAIIOProviderInterfacePrivate *private;
 
 	/**
-	 * read_tree:
+	 * read_items_list:
 	 * @instance: the #NAIIOProvider provider.
 	 *
-	 * Reads the while items tree from the specified I/O provider.
+	 * Reads the whole items list from the specified I/O provider.
 	 *
-	 * Returns: a hierarchical #GSList of menus, actions and
+	 * Returns: a unordered #GSList of menus, actions and
 	 * profiles as #NAObject-derived objects.
 	 */
 	GList *  ( *read_items_list )    ( const NAIIOProvider *instance );
diff --git a/src/common/na-ipivot-consumer.c b/src/runtime/na-ipivot-consumer.c
similarity index 99%
rename from src/common/na-ipivot-consumer.c
rename to src/runtime/na-ipivot-consumer.c
index cacbedf..e87139e 100644
--- a/src/common/na-ipivot-consumer.c
+++ b/src/runtime/na-ipivot-consumer.c
@@ -103,7 +103,7 @@ interface_base_init( NAIPivotConsumerInterface *klass )
 
 		klass->private = g_new0( NAIPivotConsumerInterfacePrivate, 1 );
 
-		klass->on_actions_changed = NULL /*do_actions_changed*/;
+		klass->on_actions_changed = NULL;
 		klass->on_display_about_changed = NULL;
 		klass->on_display_order_changed = NULL;
 
diff --git a/src/common/na-ipivot-consumer.h b/src/runtime/na-ipivot-consumer.h
similarity index 98%
rename from src/common/na-ipivot-consumer.h
rename to src/runtime/na-ipivot-consumer.h
index 20401ae..8f2098f 100644
--- a/src/common/na-ipivot-consumer.h
+++ b/src/runtime/na-ipivot-consumer.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_ipivot_consumer
  * @short_description: #NAIPivotConsumer interface definition.
- * @include: common/na-ipivot-consumer.h
+ * @include: runtime/na-ipivot-consumer.h
  *
  * This interface should be implemented by all classes which embed a
  * #NAPivot object, in order to receive modification notification
diff --git a/src/runtime/na-iprefs.c b/src/runtime/na-iprefs.c
new file mode 100644
index 0000000..563bb24
--- /dev/null
+++ b/src/runtime/na-iprefs.c
@@ -0,0 +1,413 @@
+/*
+ * 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 "na-gconf-utils.h"
+#include "na-iprefs.h"
+
+/* private interface data
+ */
+struct NAIPrefsInterfacePrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private data initialized the first time an instance calls a function
+ * of the public api
+ * it is set as a data association against the calling GObject
+ */
+typedef struct {
+	GConfClient *client;
+}
+	NAIPrefsPrivate;
+
+#define DEFAULT_ORDER_MODE_INT			IPREFS_ORDER_ALPHA_ASCENDING
+#define DEFAULT_ORDER_MODE_STR			"AscendingOrder"
+
+static GConfEnumStringPair order_mode_table[] = {
+	{ IPREFS_ORDER_ALPHA_ASCENDING ,	"AscendingOrder" },
+	{ IPREFS_ORDER_ALPHA_DESCENDING,	"DescendingOrder" },
+	{ IPREFS_ORDER_MANUAL          ,	"ManualOrder" },
+	{ 0, NULL }
+};
+
+#define NA_IPREFS_PRIVATE_DATA			"na-runtime-iprefs-private-data"
+
+static gboolean st_initialized = FALSE;
+static gboolean st_finalized = FALSE;
+
+static GType        register_type( void );
+static void         interface_base_init( NAIPrefsInterface *klass );
+static void         interface_base_finalize( NAIPrefsInterface *klass );
+
+static gboolean     read_bool( NAIPrefs *instance, const gchar *name, gboolean default_value );
+static GSList      *read_string_list( NAIPrefs *instance, const gchar *name );
+static void         write_bool( NAIPrefs *instance, const gchar *name, gboolean value );
+static void         write_string_list( NAIPrefs *instance, const gchar *name, GSList *list );
+
+static void         setup_private_data( NAIPrefs *instance );
+static GConfClient *get_gconf_client( NAIPrefs *instance );
+
+GType
+na_iprefs_get_type( void )
+{
+	static GType iface_type = 0;
+
+	if( !iface_type ){
+		iface_type = register_type();
+	}
+
+	return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_iprefs_register_type";
+	GType type;
+
+	static const GTypeInfo info = {
+		sizeof( NAIPrefsInterface ),
+		( GBaseInitFunc ) interface_base_init,
+		( GBaseFinalizeFunc ) interface_base_finalize,
+		NULL,
+		NULL,
+		NULL,
+		0,
+		0,
+		NULL
+	};
+
+	g_debug( "%s", thisfn );
+
+	type = g_type_register_static( G_TYPE_INTERFACE, "NAIPrefs", &info, 0 );
+
+	g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+	return( type );
+}
+
+static void
+interface_base_init( NAIPrefsInterface *klass )
+{
+	static const gchar *thisfn = "na_iprefs_interface_base_init";
+
+	if( !st_initialized ){
+
+		g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+		klass->private = g_new0( NAIPrefsInterfacePrivate, 1 );
+
+		st_initialized = TRUE;
+	}
+}
+
+static void
+interface_base_finalize( NAIPrefsInterface *klass )
+{
+	static const gchar *thisfn = "na_iprefs_interface_base_finalize";
+
+	if( !st_finalized ){
+
+		st_finalized = TRUE;
+
+		g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+		g_free( klass->private );
+	}
+}
+
+/**
+ * na_iprefs_get_level_zero_items:
+ * @instance: this #NAIPrefs interface instance.
+ *
+ * Returns: the ordered list of UUID's of items which are to be
+ * displayed at level zero of the hierarchy.
+ *
+ * The returned list should be na_utils_free_string_list() by the caller.
+ */
+GSList *
+na_iprefs_get_level_zero_items( NAIPrefs *instance )
+{
+	static const gchar *thisfn = "na_iprefs_get_level_zero_items";
+	GSList *level_zero = NULL;
+
+	g_debug( "%s: instance=%p (%s)", thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
+	g_return_val_if_fail( NA_IS_IPREFS( instance ), NULL );
+
+	if( st_initialized && !st_finalized ){
+
+		setup_private_data( instance );
+		level_zero = read_string_list( instance, IPREFS_LEVEL_ZERO_ITEMS );
+	}
+
+	return( level_zero );
+}
+
+/**
+ * na_iprefs_set_level_zero_items:
+ * @instance: this #NAIPrefs interface instance.
+ * @order: the ordered #GSList of item UUIDs.
+ *
+ * Writes the order and the content of the level-zero UUID's.
+ */
+void
+na_iprefs_set_level_zero_items( NAIPrefs *instance, GSList *order )
+{
+	g_return_if_fail( NA_IS_IPREFS( instance ));
+
+	if( st_initialized && !st_finalized ){
+		setup_private_data( instance );
+		write_string_list( instance, IPREFS_LEVEL_ZERO_ITEMS, order );
+	}
+}
+
+/**
+ * na_iprefs_get_order_mode:
+ * @instance: this #NAIPrefs interface instance.
+ *
+ * Returns: the order mode currently set.
+ *
+ * Note: this function returns a suitable default value even if the key
+ * is not found in GConf preferences or no schema has been installed.
+ *
+ * Note: please take care of keeping the default value synchronized with
+ * those defined in schemas.
+ */
+gint
+na_iprefs_get_order_mode( NAIPrefs *instance )
+{
+	gint alpha_order = DEFAULT_ORDER_MODE_INT;
+	gint order_int;
+	gchar *order_str;
+
+	g_return_val_if_fail( NA_IS_IPREFS( instance ), DEFAULT_ORDER_MODE_INT );
+
+	if( st_initialized && !st_finalized ){
+
+		setup_private_data( instance );
+		order_str = na_iprefs_read_string(
+				instance,
+				IPREFS_DISPLAY_ALPHABETICAL_ORDER,
+				DEFAULT_ORDER_MODE_STR );
+		if( gconf_string_to_enum( order_mode_table, order_str, &order_int )){
+			alpha_order = order_int;
+		}
+		g_free( order_str );
+	}
+
+	return( alpha_order );
+}
+
+/**
+ * na_iprefs_set_order_mode:
+ * @instance: this #NAIPrefs interface instance.
+ * @mode: the new value to be written.
+ *
+ * Writes the current status of 'alphabetical order' to the GConf
+ * preference system.
+ */
+void
+na_iprefs_set_order_mode( NAIPrefs *instance, gint mode )
+{
+	const gchar *order_str;
+
+	g_return_if_fail( NA_IS_IPREFS( instance ));
+
+	if( st_initialized && !st_finalized ){
+
+		setup_private_data( instance );
+		order_str = gconf_enum_to_string( order_mode_table, mode );
+		na_iprefs_write_string(
+				instance,
+				IPREFS_DISPLAY_ALPHABETICAL_ORDER,
+				order_str ? order_str : DEFAULT_ORDER_MODE_STR );
+	}
+}
+
+/**
+ * na_iprefs_should_add_about_item:
+ * @instance: this #NAIPrefs interface instance.
+ *
+ * Returns: #TRUE if an "About Nautilus Actions" item may be added to
+ * the first level of Nautilus context submenus (if any), #FALSE else.
+ *
+ * Note: this function returns a suitable default value if the key is
+ * not found in GConf preferences.
+ *
+ * Note: please take care of keeping the default value synchronized with
+ * those defined in schemas.
+ */
+gboolean
+na_iprefs_should_add_about_item( NAIPrefs *instance )
+{
+	gboolean about = FALSE;
+
+	g_return_val_if_fail( NA_IS_IPREFS( instance ), FALSE );
+
+	if( st_initialized && !st_finalized ){
+		setup_private_data( instance );
+		about = read_bool( instance, IPREFS_ADD_ABOUT_ITEM, TRUE );
+	}
+
+	return( about );
+}
+
+/**
+ * na_iprefs_set_add_about_item:
+ * @instance: this #NAIPrefs interface instance.
+ * @enabled: the new value to be written.
+ *
+ * Writes the new value to the GConf preference system.
+ */
+void
+na_iprefs_set_add_about_item( NAIPrefs *instance, gboolean enabled )
+{
+	g_return_if_fail( NA_IS_IPREFS( instance ));
+
+	if( st_initialized && !st_finalized ){
+		setup_private_data( instance );
+		write_bool( instance, IPREFS_ADD_ABOUT_ITEM, enabled );
+	}
+}
+
+/**
+ * na_iprefs_read_string:
+ * @instance: this #NAIPrefs interface instance.
+ * @name: the preference key.
+ * @default_value: the default value, used if entry is not found and
+ * there is no schema.
+ *
+ * Returns: the value, as a newly allocated string which should be
+ * g_free() by the caller.
+ */
+gchar *
+na_iprefs_read_string( NAIPrefs *instance, const gchar *name, const gchar *default_value )
+{
+	gchar *path;
+	gchar *value;
+
+	path = gconf_concat_dir_and_key( NA_GCONF_PREFS_PATH, name );
+	value = na_gconf_utils_read_string( get_gconf_client( instance ), path, TRUE, default_value );
+	g_free( path );
+
+	return( value );
+}
+
+/**
+ * na_iprefs_write_string:
+ * @instance: this #NAIPrefs interface instance.
+ * @name: the preference key.
+ * @value: the value to be written.
+ *
+ * Writes the value as the given GConf preference.
+ */
+void
+na_iprefs_write_string( NAIPrefs *instance, const gchar *name, const gchar *value )
+{
+	gchar *path;
+
+	path = gconf_concat_dir_and_key( NA_GCONF_PREFS_PATH, name );
+	na_gconf_utils_write_string( get_gconf_client( instance ), path, value, NULL );
+	g_free( path );
+}
+
+static gboolean
+read_bool( NAIPrefs *instance, const gchar *name, gboolean default_value )
+{
+	gchar *path;
+	gboolean ret;
+
+	path = gconf_concat_dir_and_key( NA_GCONF_PREFS_PATH, name );
+	ret = na_gconf_utils_read_bool( get_gconf_client( instance ), path, TRUE, default_value );
+	g_free( path );
+
+	return( ret );
+}
+
+static GSList *
+read_string_list( NAIPrefs *instance, const gchar *name )
+{
+	gchar *path;
+	GSList *list;
+
+	path = gconf_concat_dir_and_key( NA_GCONF_PREFS_PATH, name );
+	list = na_gconf_utils_read_string_list( get_gconf_client( instance ), path );
+	g_free( path );
+
+	return( list );
+}
+
+static void
+write_bool( NAIPrefs *instance, const gchar *name, gboolean value )
+{
+	gchar *path;
+
+	path = gconf_concat_dir_and_key( NA_GCONF_PREFS_PATH, name );
+	na_gconf_utils_write_bool( get_gconf_client( instance ), path, value, NULL );
+	g_free( path );
+}
+
+static void
+write_string_list( NAIPrefs *instance, const gchar *name, GSList *list )
+{
+	gchar *path;
+
+	path = gconf_concat_dir_and_key( NA_GCONF_PREFS_PATH, name );
+	na_gconf_utils_write_string_list( get_gconf_client( instance ), path, list, NULL );
+	g_free( path );
+}
+
+static void
+setup_private_data( NAIPrefs *instance )
+{
+	NAIPrefsPrivate *ipp;
+
+	ipp = ( NAIPrefsPrivate * ) g_object_get_data( G_OBJECT( instance ), NA_IPREFS_PRIVATE_DATA );
+	if( !ipp ){
+		ipp = g_new0( NAIPrefsPrivate, 1 );
+		ipp->client = gconf_client_get_default();
+		g_object_set_data( G_OBJECT( instance ), NA_IPREFS_PRIVATE_DATA, ipp );
+	}
+}
+
+static GConfClient *
+get_gconf_client( NAIPrefs *instance )
+{
+	NAIPrefsPrivate *ipp;
+
+	ipp = ( NAIPrefsPrivate * ) g_object_get_data( G_OBJECT( instance ), NA_IPREFS_PRIVATE_DATA );
+	g_return_val_if_fail( ipp, NULL );
+
+	return( ipp->client );
+}
diff --git a/src/runtime/na-iprefs.h b/src/runtime/na-iprefs.h
new file mode 100644
index 0000000..fa0243f
--- /dev/null
+++ b/src/runtime/na-iprefs.h
@@ -0,0 +1,125 @@
+/*
+ * 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 __NA_IPREFS_H__
+#define __NA_IPREFS_H__
+
+/**
+ * SECTION: na_iprefs
+ * @short_description: #NAIPrefs interface definition.
+ * @include: common/na-iprefs.h
+ *
+ * This interface should only be implemented by #NAPivot. This is
+ * because the interface stores as an implementor structure some data
+ * which are only relevant for one client (e.g. GConfClient).
+ *
+ * Though all modules may use the public functions na_iprefs_xxx(),
+ * only #NAPivot will receive update notifications, taking itself care
+ * of proxying them to its identified #NAIPivotConsumers.
+ *
+ * Displaying the actions.
+ *
+ * - actions in alphabetical order:
+ *
+ *   Nautilus-Actions used to display the actions in alphabetical order.
+ *   Starting with 1.12.x, Nautilus-Actions lets the user rearrange
+ *   himself the order of its actions.
+ *
+ *   This option may have three values :
+ *   - ascending alphabetical order (historical behavior, and default),
+ *   - descending alphabetical order,
+ *   - manual ordering.
+ *
+ * - adding a 'About Nautilus Actions' item at end of actions: yes/no
+ *
+ *   When checked, an 'About Nautilus Actions' is displayed as the last
+ *   item of the root submenu of Nautilus Actions actions.
+ *
+ *   It the user didn't have defined a root submenu, the plugin
+ *   provides one.
+ */
+
+#include <glib-object.h>
+
+#include "na-gconf-keys.h"
+
+G_BEGIN_DECLS
+
+#define NA_IPREFS_TYPE						( na_iprefs_get_type())
+#define NA_IPREFS( object )					( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IPREFS_TYPE, NAIPrefs ))
+#define NA_IS_IPREFS( object )				( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IPREFS_TYPE ))
+#define NA_IPREFS_GET_INTERFACE( instance )	( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IPREFS_TYPE, NAIPrefsInterface ))
+
+typedef struct NAIPrefs NAIPrefs;
+
+typedef struct NAIPrefsInterfacePrivate NAIPrefsInterfacePrivate;
+
+typedef struct {
+	GTypeInterface            parent;
+	NAIPrefsInterfacePrivate *private;
+}
+	NAIPrefsInterface;
+
+GType    na_iprefs_get_type( void );
+
+GSList  *na_iprefs_get_level_zero_items( NAIPrefs *instance );
+void     na_iprefs_set_level_zero_items( NAIPrefs *instance, GSList *order );
+
+gint     na_iprefs_get_order_mode( NAIPrefs *instance );
+void     na_iprefs_set_order_mode( NAIPrefs *instance, gint mode );
+
+gboolean na_iprefs_should_add_about_item( NAIPrefs *instance );
+void     na_iprefs_set_add_about_item( NAIPrefs *instance, gboolean enabled );
+
+gchar   *na_iprefs_read_string( NAIPrefs *instance, const gchar *key, const gchar *default_value );
+void     na_iprefs_write_string( NAIPrefs *instance, const gchar *key, const gchar *value );
+
+/* GConf keys
+ */
+#define NA_GCONF_PREFERENCES				"preferences"
+#define NA_GCONF_PREFS_PATH					NAUTILUS_ACTIONS_GCONF_BASEDIR "/" NA_GCONF_PREFERENCES
+
+/* GConf preference keys managed by IPrefs interface
+ */
+#define IPREFS_LEVEL_ZERO_ITEMS				"iprefs-level-zero"
+#define IPREFS_DISPLAY_ALPHABETICAL_ORDER	"iprefs-alphabetical-order"
+#define IPREFS_ADD_ABOUT_ITEM				"iprefs-add-about-item"
+
+/* alphabetical order values
+ */
+enum {
+	IPREFS_ORDER_ALPHA_ASCENDING = 1,
+	IPREFS_ORDER_ALPHA_DESCENDING,
+	IPREFS_ORDER_MANUAL
+};
+
+G_END_DECLS
+
+#endif /* __NA_IPREFS_H__ */
diff --git a/src/common/na-object-action-class.h b/src/runtime/na-object-action-class.h
similarity index 95%
rename from src/common/na-object-action-class.h
rename to src/runtime/na-object-action-class.h
index 2373c5e..aa20613 100644
--- a/src/common/na-object-action-class.h
+++ b/src/runtime/na-object-action-class.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_object_action
  * @short_description: #NAObjectAction class definition.
- * @include: common/na-object-action-class.h
+ * @include: runtime/na-object-action-class.h
  *
  * This is the class which maintains data and properties of an Nautilus
  * action.
@@ -48,7 +48,8 @@
  *
  * Note that a user may import an action, translate it and then
  * reexport it : we so may have two different actions with the same
- * uuid. The user has so to modify the UUID before import.
+ * uuid. The user has so to modify the UUID before import, or to
+ * select the appropriate option as an import mode.
  *
  * Note about edition status :
  *
diff --git a/src/common/na-gconf-keys-base.h b/src/runtime/na-object-action-fn.h
similarity index 53%
copy from src/common/na-gconf-keys-base.h
copy to src/runtime/na-object-action-fn.h
index 5ebc0d8..901bd9a 100644
--- a/src/common/na-gconf-keys-base.h
+++ b/src/runtime/na-object-action-fn.h
@@ -1,5 +1,5 @@
 /*
- * Nautilus Actions
+ * Nautilus ObjectActions
  * A Nautilus extension which offers configurable context menu actions.
  *
  * Copyright (C) 2005 The GNOME Foundation
@@ -28,16 +28,35 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_GCONF_KEYS_BASE_H__
-#define __NA_GCONF_KEYS_BASE_H__
+#ifndef __NA_OBJECT_ACTION_FN_H__
+#define __NA_OBJECT_ACTION_FN_H__
 
-/* GConf general information
- *
- * They are used both:
- * - by GConf as a NAIIOProvider
- * - by GConf as the preferences storage system
- * - for providing schemas in import/export actions
+/**
+ * SECTION: na_object_action
+ * @short_description: #NAObjectAction public function declaration.
+ * @include: runtime/na-object-action.h
  */
-#define NAUTILUS_ACTIONS_GCONF_BASEDIR			"/apps/nautilus-actions"
 
-#endif /* __NA_GCONF_KEYS_BASE_H__ */
+#include <glib/gi18n.h>
+
+#include "na-object-action-class.h"
+#include "na-object-profile-class.h"
+
+G_BEGIN_DECLS
+
+/* i18n: default label for a newly created action */
+#define NA_OBJECT_ACTION_DEFAULT_LABEL		_( "New Nautilus action" )
+
+NAObjectAction *na_object_action_new( void );
+
+gchar          *na_object_action_get_version( const NAObjectAction *action );
+
+void            na_object_action_set_version( NAObjectAction *action, const gchar *version );
+void            na_object_action_set_readonly( NAObjectAction *action, gboolean readonly );
+
+gchar          *na_object_action_get_new_profile_name( const NAObjectAction *action );
+void            na_object_action_attach_profile( NAObjectAction *action, NAObjectProfile *profile );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_ACTION_FN_H__ */
diff --git a/src/runtime/na-object-action.c b/src/runtime/na-object-action.c
new file mode 100644
index 0000000..b47bb76
--- /dev/null
+++ b/src/runtime/na-object-action.c
@@ -0,0 +1,585 @@
+/*
+ * 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 <string.h>
+
+#include "na-iduplicable.h"
+#include "na-object-api.h"
+#include "na-utils.h"
+
+/* private class data
+ */
+struct NAObjectActionClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectActionPrivate {
+	gboolean dispose_has_run;
+
+	/* action properties
+	 */
+	gchar   *version;
+
+	/* dynamically set when reading the actions from the I/O storage
+	 * subsystem
+	 * defaults to FALSE unless a write has already returned an error
+	 */
+	gboolean read_only;
+};
+
+/* action properties
+ */
+enum {
+	NAACTION_PROP_VERSION_ID = 1,
+	NAACTION_PROP_READONLY_ID
+};
+
+#define NAACTION_PROP_VERSION			"na-action-version"
+#define NAACTION_PROP_READONLY			"na-action-read-only"
+
+static NAObjectItemClass *st_parent_class = NULL;
+
+static GType     register_type( void );
+static void      class_init( NAObjectActionClass *klass );
+static void      instance_init( GTypeInstance *instance, gpointer klass );
+static void      instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void      instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void      instance_dispose( GObject *object );
+static void      instance_finalize( GObject *object );
+
+static void      object_dump( const NAObject *object );
+static NAObject *object_new( const NAObject *action );
+static void      object_copy( NAObject *target, const NAObject *source );
+static gboolean  object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean  object_is_valid( const NAObject *object );
+
+GType
+na_object_action_get_type( void )
+{
+	static GType action_type = 0;
+
+	if( !action_type ){
+		action_type = register_type();
+	}
+
+	return( action_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_object_action_register_type";
+
+	static GTypeInfo info = {
+		sizeof( NAObjectActionClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NAObjectAction ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	return( g_type_register_static( NA_OBJECT_ITEM_TYPE, "NAObjectAction", &info, 0 ));
+}
+
+static void
+class_init( NAObjectActionClass *klass )
+{
+	static const gchar *thisfn = "na_object_action_class_init";
+	GObjectClass *object_class;
+	NAObjectClass *naobject_class;
+	GParamSpec *spec;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+	object_class->set_property = instance_set_property;
+	object_class->get_property = instance_get_property;
+
+	spec = g_param_spec_string(
+			NAACTION_PROP_VERSION,
+			"Version",
+			"Version of the schema", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAACTION_PROP_VERSION_ID, spec );
+
+	spec = g_param_spec_boolean(
+			NAACTION_PROP_READONLY,
+			"Read-only flag",
+			"Is this action only readable", FALSE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAACTION_PROP_READONLY_ID, spec );
+
+	klass->private = g_new0( NAObjectActionClassPrivate, 1 );
+
+	naobject_class = NA_OBJECT_CLASS( klass );
+	naobject_class->dump = object_dump;
+	naobject_class->new = object_new;
+	naobject_class->copy = object_copy;
+	naobject_class->are_equal = object_are_equal;
+	naobject_class->is_valid = object_is_valid;
+	naobject_class->get_childs = NULL;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	/*static const gchar *thisfn = "na_object_action_instance_init";*/
+	NAObjectAction *self;
+
+	/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+	g_return_if_fail( NA_IS_OBJECT_ACTION( instance ));
+	self = NA_OBJECT_ACTION( instance );
+
+	self->private = g_new0( NAObjectActionPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+
+	/* initialize suitable default values
+	 */
+	self->private->version = g_strdup( NAUTILUS_ACTIONS_CONFIG_VERSION );
+	self->private->read_only = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	NAObjectAction *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+	self = NA_OBJECT_ACTION( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAACTION_PROP_VERSION_ID:
+				g_value_set_string( value, self->private->version );
+				break;
+
+			case NAACTION_PROP_READONLY_ID:
+				g_value_set_boolean( value, self->private->read_only );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+	NAObjectAction *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+	self = NA_OBJECT_ACTION( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAACTION_PROP_VERSION_ID:
+				g_free( self->private->version );
+				self->private->version = g_value_dup_string( value );
+				break;
+
+			case NAACTION_PROP_READONLY_ID:
+				self->private->read_only = g_value_get_boolean( value );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_instance_dispose";*/
+	NAObjectAction *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+	self = NA_OBJECT_ACTION( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_instance_finalize";*/
+	NAObjectAction *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+	self = NA_OBJECT_ACTION( object );
+
+	g_free( self->private->version );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * na_object_action_new:
+ *
+ * Allocates a new #NAObjectAction object.
+ *
+ * The new #NAObjectAction object is initialized with suitable default values,
+ * but without any profile.
+ *
+ * Returns: the newly allocated #NAObjectAction object.
+ */
+NAObjectAction *
+na_object_action_new( void )
+{
+	NAObjectAction *action;
+
+	action = g_object_new( NA_OBJECT_ACTION_TYPE, NULL );
+
+	na_object_set_new_id( action, NULL );
+
+	/* i18n: default label for a new action */
+	na_object_set_label( action, NA_OBJECT_ACTION_DEFAULT_LABEL );
+
+	return( action );
+}
+
+/**
+ * na_object_action_get_version:
+ * @action: the #NAObjectAction object to be requested.
+ *
+ * Returns the version of the description of the action, as found when
+ * reading it from the I/O storage subsystem.
+ *
+ * Returns: the version of the action as a newly allocated string. This
+ * returned string must be g_free() by the caller.
+ *
+ * See na_object_set_version() for some rationale about version.
+ */
+gchar *
+na_object_action_get_version( const NAObjectAction *action )
+{
+	gchar *version = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), NULL );
+
+	if( !action->private->dispose_has_run ){
+		g_object_get( G_OBJECT( action ), NAACTION_PROP_VERSION, &version, NULL );
+	}
+
+	return( version );
+}
+
+/**
+ * na_object_action_set_version:
+ * @action: the #NAObjectAction object to be updated.
+ * @label: the label to be set.
+ *
+ * Sets a new version for the action.
+ *
+ * #NAObjectAction takes a copy of the provided version. This later may so be
+ * g_free() by the caller after this function returns.
+ *
+ * The version describes the schema of the informations in the I/O
+ * storage subsystem.
+ *
+ * Version is stored in the #NAObjectAction object as readen from the I/O
+ * storage subsystem, even if the #NAObjectAction object itself only reflects
+ * the lastest known version. Conversion is made at load time (cf.
+ * na_gconf_load_action()).
+ */
+void
+na_object_action_set_version( NAObjectAction *action, const gchar *version )
+{
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+
+	if( !action->private->dispose_has_run ){
+		g_object_set( G_OBJECT( action ), NAACTION_PROP_VERSION, version, NULL );
+	}
+}
+
+/**
+ * na_object_action_set_readonly:
+ * @action: the #NAObjectAction object to be updated.
+ * @readonly: the indicator to be set.
+ *
+ * Sets whether the action is readonly.
+ */
+void
+na_object_action_set_readonly( NAObjectAction *action, gboolean readonly )
+{
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+
+	if( !action->private->dispose_has_run ){
+		g_object_set( G_OBJECT( action ), NAACTION_PROP_READONLY, readonly, NULL );
+	}
+}
+
+/**
+ * na_object_action_get_new_profile_name:
+ * @action: the #NAObjectAction object which will receive a new profile.
+ *
+ * Returns a name suitable as a new profile name.
+ *
+ * The search is made by iterating over the standard profile name
+ * prefix : basically, we increment a counter until finding a unique
+ * name. The provided name is so only suitable for the specified
+ * @action.
+ *
+ * Returns: a newly allocated profile name, which should be g_free() by
+ * the caller.
+ */
+gchar *
+na_object_action_get_new_profile_name( const NAObjectAction *action )
+{
+	int i;
+	gboolean ok = FALSE;
+	gchar *candidate = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), NULL );
+
+	if( !action->private->dispose_has_run ){
+
+		for( i=1 ; !ok ; ++i ){
+			g_free( candidate );
+			candidate = g_strdup_printf( "%s%d", OBJECT_PROFILE_PREFIX, i );
+			if( !na_object_get_item( action, candidate )){
+				ok = TRUE;
+			}
+		}
+
+		if( !ok ){
+			g_free( candidate );
+			candidate = NULL;
+		}
+	}
+
+	return( candidate );
+}
+
+/**
+ * na_object_action_attach_profile:
+ * @action: the #NAObjectAction action to which the profile will be attached.
+ * @profile: the #NAObjectProfile profile to be attached to @action.
+ *
+ * Adds a profile at the end of the list of profiles.
+ */
+void
+na_object_action_attach_profile( NAObjectAction *action, NAObjectProfile *profile )
+{
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !action->private->dispose_has_run ){
+
+		na_object_append_item( action, profile );
+		na_object_profile_set_action( profile, action );
+	}
+}
+
+static void
+object_dump( const NAObject *action )
+{
+	static const gchar *thisfn = "na_object_action_object_dump";
+	NAObjectAction *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+	self = NA_OBJECT_ACTION( action );
+
+	if( !self->private->dispose_has_run ){
+
+		g_debug( "%s:   version='%s'", thisfn, self->private->version );
+		g_debug( "%s: read-only='%s'", thisfn, self->private->read_only ? "True" : "False" );
+	}
+}
+
+static NAObject *
+object_new( const NAObject *action )
+{
+	return( NA_OBJECT( na_object_action_new()));
+}
+
+void
+object_copy( NAObject *target, const NAObject *source )
+{
+	gchar *version;
+	gboolean readonly;
+	GList *profiles, *ip;
+
+	g_return_if_fail( NA_IS_OBJECT_ACTION( target ));
+	g_return_if_fail( NA_IS_OBJECT_ACTION( source ));
+
+	if( !NA_OBJECT_ACTION( target )->private->dispose_has_run &&
+		!NA_OBJECT_ACTION( source )->private->dispose_has_run ){
+
+		g_object_get( G_OBJECT( source ),
+				NAACTION_PROP_VERSION, &version,
+				NAACTION_PROP_READONLY, &readonly,
+				NULL );
+
+		g_object_set( G_OBJECT( target ),
+				NAACTION_PROP_VERSION, version,
+				NAACTION_PROP_READONLY, readonly,
+				NULL );
+
+		g_free( version );
+
+		/* profiles have been copied (duplicated) as subitems by parent class
+		 * we have to attach new profiles to target action
+		 */
+		profiles = na_object_get_items( target );
+		for( ip = profiles ; ip ; ip = ip->next ){
+			na_object_profile_set_action( NA_OBJECT_PROFILE( ip->data ), NA_OBJECT_ACTION( target ));
+		}
+		na_object_free_items( profiles );
+	}
+}
+
+/*
+ * note 1: version is not localized (see configure.ac)
+ *
+ * note 2: when checking for equality of profiles, we know that NAObjectItem
+ * has already checked their edition status, and that the two profiles lists
+ * were the sames ; we so only report the modification status to the action
+ */
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+	NAObjectAction *first, *second;
+	gboolean equal = TRUE;
+	GList *profiles, *ip;
+	gchar *id;
+	NAObjectProfile *profile;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ACTION( a ), FALSE );
+	first = NA_OBJECT_ACTION( a );
+
+	g_return_val_if_fail( NA_IS_OBJECT_ACTION( b ), FALSE );
+	second = NA_OBJECT_ACTION( b );
+
+	if( !NA_OBJECT_ACTION( a )->private->dispose_has_run &&
+		!NA_OBJECT_ACTION( b )->private->dispose_has_run ){
+
+		if( equal ){
+			equal = ( strcmp( first->private->version, second->private->version ) == 0 );
+		}
+
+		if( equal ){
+			profiles = na_object_get_items( a );
+			for( ip = profiles ; ip && equal ; ip = ip->next ){
+				id = na_object_get_id( ip->data );
+				profile = NA_OBJECT_PROFILE( na_object_get_item( b, id ));
+				equal = !na_object_is_modified( profile );
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+				if( !equal ){
+					g_debug( "na_object_action_are_equal: profile=%p, equal=False", ( void * ) profile );
+				}
+#endif
+
+				g_free( id );
+			}
+			na_object_free_items( profiles );
+		}
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+		g_debug( "na_object_action_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+				( void * ) a, G_OBJECT_TYPE_NAME( a ),
+				( void * ) b, G_OBJECT_TYPE_NAME( b ),
+				equal ? "True":"False" );
+#endif
+	}
+
+	return( equal );
+}
+
+/*
+ * a valid NAObjectAction requires a not null, not empty label
+ * this is checked here as NAObjectId doesn't have this condition
+ *
+ * and at least one profile
+ * checked here because NAObjectItem doesn't have this condition
+ */
+gboolean
+object_is_valid( const NAObject *action )
+{
+	gchar *label;
+	gboolean is_valid = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
+
+	if( !NA_OBJECT_ACTION( action )->private->dispose_has_run ){
+
+		if( is_valid ){
+			label = na_object_get_label( NA_OBJECT_ACTION( action ));
+			is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
+			g_free( label );
+		}
+
+		if( is_valid ){
+			is_valid = ( na_object_get_items_count( action ) >= 1 );
+		}
+	}
+
+	return( is_valid );
+}
diff --git a/src/runtime/na-object-api.h b/src/runtime/na-object-api.h
new file mode 100644
index 0000000..9fdb28b
--- /dev/null
+++ b/src/runtime/na-object-api.h
@@ -0,0 +1,96 @@
+/*
+ * 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 __NA_OBJECT_API_H__
+#define __NA_OBJECT_API_H__
+
+/**
+ * SECTION: na_object
+ * @short_description: #NAObject public API.
+ * @include: runtime/na-object-api.h
+ *
+ * We define here a common API which makes easier to write (and read)
+ * the code ; all object functions are named na_object ; all arguments
+ * are casted directly in the macro.
+ *
+ * Only define here the API which is relevant in libna-runtime library.
+ */
+
+#include "na-object-fn.h"
+#include "na-object-id-fn.h"
+#include "na-object-item-fn.h"
+#include "na-object-menu-fn.h"
+#include "na-object-action-fn.h"
+#include "na-object-profile-fn.h"
+
+G_BEGIN_DECLS
+
+/* NAObject
+ */
+#define na_object_dump( object )					na_object_object_dump( NA_OBJECT( object ))
+#define na_object_dump_norec( object )				na_object_object_dump_norec( NA_OBJECT( object ))
+#define na_object_dump_tree( tree )					na_object_object_dump_tree( tree )
+
+/* NAIDuplicable
+ */
+#define na_object_duplicate( object )				na_object_iduplicable_duplicate( NA_OBJECT( object ))
+#define na_object_is_modified( object )				na_object_iduplicable_is_modified( NA_OBJECT( object ))
+
+/* NAObjectId
+ */
+#define na_object_get_id( object )					na_object_id_get_id( NA_OBJECT_ID( object ))
+#define na_object_get_label( object )				na_object_id_get_label( NA_OBJECT_ID( object ))
+
+#define na_object_set_id( object, id )				na_object_id_set_id( NA_OBJECT_ID( object ), id )
+#define na_object_set_new_id( object, parent )		na_object_id_set_new_id( NA_OBJECT_ID( object ), ( NAObjectId * ) parent )
+#define na_object_set_label( object, label )		na_object_id_set_label( NA_OBJECT_ID( object ), label )
+
+/* NAObjectItem
+ */
+#define na_object_get_tooltip( object )				na_object_item_get_tooltip( NA_OBJECT_ITEM( object ))
+#define na_object_get_icon( object )				na_object_item_get_icon( NA_OBJECT_ITEM( object ))
+#define na_object_get_provider( object )			na_object_item_get_provider( NA_OBJECT_ITEM( object ))
+#define na_object_is_enabled( object )				na_object_item_is_enabled( NA_OBJECT_ITEM( object ))
+#define na_object_get_item( object, id )			na_object_item_get_item( NA_OBJECT_ITEM( object ), id )
+#define na_object_get_items( object )				na_object_item_get_items( NA_OBJECT_ITEM( object ))
+#define na_object_get_items_count( object )			na_object_item_get_items_count( NA_OBJECT_ITEM( object ))
+#define na_object_free_items( list )				na_object_item_free_items( list )
+
+#define na_object_set_tooltip( object, tooltip )	na_object_item_set_tooltip( NA_OBJECT_ITEM( object ), tooltip )
+#define na_object_set_icon( object, icon )			na_object_item_set_icon( NA_OBJECT_ITEM( object ), icon )
+#define na_object_set_provider( object, provider )	na_object_item_set_provider( NA_OBJECT_ITEM( object ), provider )
+#define na_object_set_enabled( object, enabled )	na_object_item_set_enabled( NA_OBJECT_ITEM( object ), enabled )
+#define na_object_set_items( object, list )			na_object_item_set_items( NA_OBJECT_ITEM( object ), list )
+
+#define na_object_append_item( object, item )		na_object_item_append_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_API_H__ */
diff --git a/src/common/na-object-class.h b/src/runtime/na-object-class.h
similarity index 87%
rename from src/common/na-object-class.h
rename to src/runtime/na-object-class.h
index 07506b8..fd53b06 100644
--- a/src/common/na-object-class.h
+++ b/src/runtime/na-object-class.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_object
  * @short_description: #NAObject class definition.
- * @include: common/na-object-class.h
+ * @include: runtime/na-object-class.h
  *
  * This is the base class for managed objects.
  *
@@ -84,32 +84,6 @@ typedef struct {
 	void       ( *dump )            ( const NAObject *object );
 
 	/**
-	 * get_clipboard_id:
-	 * @object: the #NAObject-derived object whose id is to be
-	 * retrieved.
-	 *
-	 * Returns: an id suitable for our internal clipboard.
-	 *
-	 * This is a pure virtual function: the most derived class should
-	 * implement it. #NAObject class defaults to return the clipboard
-	 * id of the most derived class which implement this function.
-	 */
-	gchar *    ( *get_clipboard_id )( const NAObject *object );
-
-	/**
-	 * ref:
-	 * @object: the #NAObject-derived object to be reffed.
-	 *
-	 * Returns: a reference on the #NAObject.
-	 *
-	 * #NAObject public api implements a bottom-to-top iteration.
-	 * Each derived class has only to take care of ref-ing its own
-	 * childs if applies.
-	 * Finally, the #NAObject class will ref this @object itself.
-	 */
-	void       ( *ref )             ( const NAObject *object );
-
-	/**
 	 * new:
 	 * @object: a #NAObject-derived object of the class that we want
 	 * be returned.
diff --git a/src/common/na-gconf-keys-base.h b/src/runtime/na-object-fn.h
similarity index 57%
copy from src/common/na-gconf-keys-base.h
copy to src/runtime/na-object-fn.h
index 5ebc0d8..d07e82a 100644
--- a/src/common/na-gconf-keys-base.h
+++ b/src/runtime/na-object-fn.h
@@ -28,16 +28,38 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_GCONF_KEYS_BASE_H__
-#define __NA_GCONF_KEYS_BASE_H__
+#ifndef __NA_OBJECT_FN_H__
+#define __NA_OBJECT_FN_H__
 
-/* GConf general information
+/**
+ * SECTION: na_object
+ * @short_description: #NAObject public functions declarations.
+ * @include: runtime/na-object-fn.h
  *
- * They are used both:
- * - by GConf as a NAIIOProvider
- * - by GConf as the preferences storage system
- * - for providing schemas in import/export actions
+ * Define here the public functions of the #NAObject class.
+ *
+ * Note that most users of the class should rather use macros defined
+ * in na-object-api.h
+ */
+
+#include "na-object-class.h"
+
+G_BEGIN_DECLS
+
+/* NAIDuplicable
  */
-#define NAUTILUS_ACTIONS_GCONF_BASEDIR			"/apps/nautilus-actions"
+NAObject *na_object_iduplicable_duplicate( const NAObject *object );
+gboolean  na_object_iduplicable_is_modified( const NAObject *object );
+
+/* NAObject
+ */
+void      na_object_object_dump( const NAObject *object );
+void      na_object_object_dump_norec( const NAObject *object );
+void      na_object_object_dump_tree( GList *tree );
+
+GList    *na_object_get_hierarchy( const NAObject *object );
+void      na_object_free_hierarchy( GList *hierarchy );
+
+G_END_DECLS
 
-#endif /* __NA_GCONF_KEYS_BASE_H__ */
+#endif /* __NA_OBJECT_FN_H__ */
diff --git a/src/common/na-object-id-class.h b/src/runtime/na-object-id-class.h
similarity index 88%
rename from src/common/na-object-id-class.h
rename to src/runtime/na-object-id-class.h
index 239f7f9..31599f4 100644
--- a/src/common/na-object-id-class.h
+++ b/src/runtime/na-object-id-class.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_object_id
  * @short_description: #NAObjectId class definition.
- * @include: common/na-object-id-class.h
+ * @include: runtime/na-object-id-class.h
  *
  * A #NAObjectId object is characterized by :
  * - an internal identifiant (ASCII, case insensitive)
@@ -71,14 +71,19 @@ typedef struct {
 	/**
 	 * new_id:
 	 * @object: a #NAObjectId object.
+	 * @new_parent: possibly the new #NAObjectId parent, or NULL.
 	 *
 	 * Returns: a new id suitable for this @object.
 	 *
+	 * If @object is a #NAObjectProfile, then @new_parent must be a
+	 * not null #NAObjectAction. This function ensures that the new
+	 * profile name does not already exist in the given @new_parent.
+	 *
 	 * This is a pure virtual function which should be implemented by
 	 * the actual class. Actually, we asks for the most-derived class
 	 * which implements this function.
 	 */
-	gchar * ( *new_id )( const NAObjectId *object );
+	gchar * ( *new_id )( const NAObjectId *object, const NAObjectId *new_parent );
 }
 	NAObjectIdClass;
 
diff --git a/src/common/na-gconf-keys-base.h b/src/runtime/na-object-id-fn.h
similarity index 60%
copy from src/common/na-gconf-keys-base.h
copy to src/runtime/na-object-id-fn.h
index 5ebc0d8..9bf2a0a 100644
--- a/src/common/na-gconf-keys-base.h
+++ b/src/runtime/na-object-id-fn.h
@@ -28,16 +28,31 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_GCONF_KEYS_BASE_H__
-#define __NA_GCONF_KEYS_BASE_H__
+#ifndef __NA_OBJECT_ID_FN_H__
+#define __NA_OBJECT_ID_FN_H__
 
-/* GConf general information
+/**
+ * SECTION: na_object_id
+ * @short_description: #NAObjectId public function declarations.
+ * @include: runtime/na-object-id-fn.h
  *
- * They are used both:
- * - by GConf as a NAIIOProvider
- * - by GConf as the preferences storage system
- * - for providing schemas in import/export actions
+ * Define here the public functions of the #NAObjectId class.
+ *
+ * Note that most users of the class should rather use macros defined
+ * in na-object-api.h
  */
-#define NAUTILUS_ACTIONS_GCONF_BASEDIR			"/apps/nautilus-actions"
 
-#endif /* __NA_GCONF_KEYS_BASE_H__ */
+#include "na-object-id-class.h"
+
+G_BEGIN_DECLS
+
+gchar *na_object_id_get_id( const NAObjectId *object );
+void   na_object_id_set_new_id( NAObjectId *object, const NAObjectId *new_parent );
+gchar *na_object_id_get_label( const NAObjectId *object );
+
+void   na_object_id_set_id( NAObjectId *object, const gchar *id );
+void   na_object_id_set_label( NAObjectId *object, const gchar *label );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_ID_FN_H__ */
diff --git a/src/runtime/na-object-id.c b/src/runtime/na-object-id.c
new file mode 100644
index 0000000..a8f5824
--- /dev/null
+++ b/src/runtime/na-object-id.c
@@ -0,0 +1,518 @@
+/*
+ * 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 <glib/gi18n.h>
+#include <string.h>
+
+#include "na-iduplicable.h"
+#include "na-object-api.h"
+
+/* private class data
+ */
+struct NAObjectIdClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectIdPrivate {
+	gboolean  dispose_has_run;
+	gchar    *id;
+	gchar    *label;
+};
+
+/* object properties
+ */
+enum {
+	NAOBJECT_ID_PROP_ID_ID = 1,
+	NAOBJECT_ID_PROP_LABEL_ID
+};
+
+/* instance properties
+ */
+#define NAOBJECT_ID_PROP_ID				"na-object-id"
+#define NAOBJECT_ID_PROP_LABEL			"na-object-label"
+
+static NAObjectClass *st_parent_class = NULL;
+
+static GType    register_type( void );
+static void     class_init( NAObjectIdClass *klass );
+static void     instance_init( GTypeInstance *instance, gpointer klass );
+static void     instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void     instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void     instance_dispose( GObject *object );
+static void     instance_finalize( GObject *object );
+
+static void     object_dump( const NAObject *object);
+static void     object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *object );
+
+static gchar   *v_new_id( const NAObjectId *object, const NAObjectId *new_parent );
+static gchar   *most_derived_new_id( const NAObjectId *object, const NAObjectId *new_parent );
+
+GType
+na_object_id_get_type( void )
+{
+	static GType object_type = 0;
+
+	if( !object_type ){
+		object_type = register_type();
+	}
+
+	return( object_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_object_id_register_type";
+	GType type;
+
+	static GTypeInfo info = {
+		sizeof( NAObjectIdClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NAObjectId ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	type = g_type_register_static( NA_OBJECT_TYPE, "NAObjectId", &info, 0 );
+
+	return( type );
+}
+
+static void
+class_init( NAObjectIdClass *klass )
+{
+	static const gchar *thisfn = "na_object_id_class_init";
+	GObjectClass *object_class;
+	NAObjectClass *naobject_class;
+	GParamSpec *spec;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+	object_class->set_property = instance_set_property;
+	object_class->get_property = instance_get_property;
+
+	spec = g_param_spec_string(
+			NAOBJECT_ID_PROP_ID,
+			"NAObjectId identifiant",
+			"Internal identifiant of the NAObjectId object (ASCII, case insensitive)", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAOBJECT_ID_PROP_ID_ID, spec );
+
+	spec = g_param_spec_string(
+			NAOBJECT_ID_PROP_LABEL,
+			"NAObjectId libelle",
+			"Libelle of the NAObjectId object (UTF-8, localizable)", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAOBJECT_ID_PROP_LABEL_ID, spec );
+
+	klass->private = g_new0( NAObjectIdClassPrivate, 1 );
+
+	naobject_class = NA_OBJECT_CLASS( klass );
+	naobject_class->dump = object_dump;
+	naobject_class->new = NULL;
+	naobject_class->copy = object_copy;
+	naobject_class->are_equal = object_are_equal;
+	naobject_class->is_valid = object_is_valid;
+	naobject_class->get_childs = NULL;
+
+	klass->new_id = NULL;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	/*static const gchar *thisfn = "na_object_id_instance_init";*/
+	NAObjectId *self;
+
+	/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+	g_return_if_fail( NA_IS_OBJECT_ID( instance ));
+	self = NA_OBJECT_ID( instance );
+
+	self->private = g_new0( NAObjectIdPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	NAObjectId *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+	self = NA_OBJECT_ID( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAOBJECT_ID_PROP_ID_ID:
+				g_value_set_string( value, self->private->id );
+				break;
+
+			case NAOBJECT_ID_PROP_LABEL_ID:
+				g_value_set_string( value, self->private->label );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+	NAObjectId *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+	self = NA_OBJECT_ID( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAOBJECT_ID_PROP_ID_ID:
+				g_free( self->private->id );
+				self->private->id = g_value_dup_string( value );
+				break;
+
+			case NAOBJECT_ID_PROP_LABEL_ID:
+				g_free( self->private->label );
+				self->private->label = g_value_dup_string( value );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_id_instance_dispose";*/
+	NAObjectId *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+	self = NA_OBJECT_ID( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	NAObjectId *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+	self = NA_OBJECT_ID( object );
+
+	g_free( self->private->id );
+	g_free( self->private->label );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * na_object_id_get_id:
+ * @object: the #NAObjectId object whose internal identifiant is
+ * requested.
+ *
+ * Returns: the internal identifiant of @object as a new string.
+ *
+ * The returned string is an ASCII, case insensitive, string.
+ * It should be g_free() by the caller.
+ */
+gchar *
+na_object_id_get_id( const NAObjectId *object )
+{
+	gchar *id = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ID( object ), NULL );
+
+	if( !object->private->dispose_has_run ){
+		g_object_get( G_OBJECT( object ), NAOBJECT_ID_PROP_ID, &id, NULL );
+	}
+
+	return( id );
+}
+
+/**
+ * na_object_id_get_label:
+ * @object: the #NAObjectId object whose label is requested.
+ *
+ * Returns: the label of @object as a new string.
+ *
+ * The returned string is an UTF_8 localizable string.
+ * It should be g_free() by the caller.
+ */
+gchar *
+na_object_id_get_label( const NAObjectId *object )
+{
+	gchar *label = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ID( object ), NULL );
+
+	if( !object->private->dispose_has_run ){
+		g_object_get( G_OBJECT( object ), NAOBJECT_ID_PROP_LABEL, &label, NULL );
+	}
+
+	return( label );
+}
+
+/**
+ * na_object_id_set_id:
+ * @object: the #NAObjectId object whose internal identifiant is to be
+ * set.
+ * @id: internal identifiant to be set.
+ *
+ * Sets the internal identifiant of @object by taking a copy of the
+ * provided one.
+ */
+void
+na_object_id_set_id( NAObjectId *object, const gchar *id )
+{
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+
+	if( !object->private->dispose_has_run ){
+		g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_ID, id, NULL );
+	}
+}
+
+/**
+ * na_object_id_set_new_id:
+ * @object: the #NAObjectId object whose internal identifiant is to be
+ * set.
+ * @new_parent: if @object is a #NAObjectProfile, then @new_parent
+ * should be set to the #NAObjectActio new parent. Else, it would not
+ * be possible to allocate a new profile id compatible with already
+ * existing ones.
+ *
+ * Request a new id to the derived class, and set it.
+ */
+void
+na_object_id_set_new_id( NAObjectId *object, const NAObjectId *new_parent )
+{
+	gchar *id;
+
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+	g_return_if_fail( !new_parent || NA_IS_OBJECT_ID( new_parent ));
+
+	if( !object->private->dispose_has_run ){
+
+		id = v_new_id( object, new_parent );
+
+		if( id ){
+			g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_ID, id, NULL );
+			g_free( id );
+		}
+	}
+}
+
+/**
+ * na_object_id_set_label:
+ * @object: the #NAObjectId object whose label is to be set.
+ * @label: label to be set.
+ *
+ * Sets the label of @object by taking a copy of the provided one.
+ */
+void
+na_object_id_set_label( NAObjectId *object, const gchar *label )
+{
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+
+	if( !object->private->dispose_has_run ){
+		g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_LABEL, label, NULL );
+	}
+}
+
+static void
+object_dump( const NAObject *object )
+{
+	static const char *thisfn = "na_object_id_object_dump";
+
+	g_return_if_fail( NA_IS_OBJECT_ID( object ));
+
+	if( !NA_OBJECT_ID( object )->private->dispose_has_run ){
+
+		g_debug( "%s:    id=%s", thisfn, NA_OBJECT_ID( object )->private->id );
+		g_debug( "%s: label=%s", thisfn, NA_OBJECT_ID( object )->private->label );
+	}
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+	gchar *id, *label;
+
+	g_return_if_fail( NA_IS_OBJECT_ID( target ));
+	g_return_if_fail( NA_IS_OBJECT_ID( source ));
+
+	if( !NA_OBJECT_ID( target )->private->dispose_has_run &&
+		!NA_OBJECT_ID( source )->private->dispose_has_run ){
+
+			g_object_get( G_OBJECT( source ),
+					NAOBJECT_ID_PROP_ID, &id,
+					NAOBJECT_ID_PROP_LABEL, &label,
+					NULL );
+
+			g_object_set( G_OBJECT( target ),
+					NAOBJECT_ID_PROP_ID, id,
+					NAOBJECT_ID_PROP_LABEL, label,
+					NULL );
+
+			g_free( id );
+			g_free( label );
+	}
+}
+
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+	gboolean equal = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ID( a ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT_ID( b ), FALSE );
+
+	if( !NA_OBJECT_ID( a )->private->dispose_has_run &&
+		!NA_OBJECT_ID( b )->private->dispose_has_run ){
+
+			if( equal ){
+				if( g_ascii_strcasecmp( NA_OBJECT_ID( a )->private->id, NA_OBJECT_ID( b )->private->id )){
+					/*g_debug( "a->id=%s, b->id=%s", NA_OBJECT_ID( a )->private->id, NA_OBJECT_ID( b )->private->id );*/
+					equal = FALSE;
+				}
+			}
+
+			if( equal ){
+				if( g_utf8_collate( NA_OBJECT_ID( a )->private->label, NA_OBJECT_ID( b )->private->label )){
+					/*g_debug( "a->label=%s, b->label=%s", NA_OBJECT_ID( a )->private->label, NA_OBJECT_ID( b )->private->label );*/
+					equal = FALSE;
+				}
+			}
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+			g_debug( "na_object_id_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+					( void * ) a, G_OBJECT_TYPE_NAME( a ),
+					( void * ) b, G_OBJECT_TYPE_NAME( b ),
+					equal ? "True":"False" );
+#endif
+	}
+
+	return( equal );
+}
+
+/*
+ * from NAObjectId point of view, a valid object requires an id
+ * (not null, not empty)
+ */
+static gboolean
+object_is_valid( const NAObject *object )
+{
+	gboolean valid = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ID( object ), FALSE );
+
+	if( !NA_OBJECT_ID( object )->private->dispose_has_run ){
+
+		if( valid ){
+			valid = ( NA_OBJECT_ID( object )->private->id && strlen( NA_OBJECT_ID( object )->private->id ));
+		}
+	}
+
+	return( valid );
+}
+
+static gchar *
+v_new_id( const NAObjectId *object, const NAObjectId *new_parent )
+{
+	return( most_derived_new_id( object, new_parent ));
+}
+
+static gchar *
+most_derived_new_id( const NAObjectId *object, const NAObjectId *new_parent )
+{
+	gchar *new_id;
+	GList *hierarchy, *ih;
+	gboolean found;
+
+	found = FALSE;
+	new_id = NULL;
+	hierarchy = g_list_reverse( na_object_get_hierarchy( NA_OBJECT( object )));
+	/*g_debug( "na_object_id_most_derived_id: object=%p (%s)",
+					( void * ) object, G_OBJECT_TYPE_NAME( object ));*/
+
+	for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+		if( NA_OBJECT_ID_CLASS( ih->data )->new_id ){
+			new_id = NA_OBJECT_ID_CLASS( ih->data )->new_id( object, new_parent );
+			found = TRUE;
+		}
+		if( G_OBJECT_CLASS_TYPE( ih->data ) == NA_OBJECT_ID_TYPE ){
+			break;
+		}
+	}
+
+	na_object_free_hierarchy( hierarchy );
+
+	return( new_id );
+}
diff --git a/src/common/na-object-item-class.h b/src/runtime/na-object-item-class.h
similarity index 98%
rename from src/common/na-object-item-class.h
rename to src/runtime/na-object-item-class.h
index a724f51..3f748c2 100644
--- a/src/common/na-object-item-class.h
+++ b/src/runtime/na-object-item-class.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_object_item
  * @short_description: #NAObjectItem class definition.
- * @include: common/na-object-item-class.h
+ * @include: runtime/na-object-item-class.h
  *
  * Derived from #NAObjectId class, this class implements objects which
  * have :
diff --git a/src/runtime/na-object-item-fn.h b/src/runtime/na-object-item-fn.h
new file mode 100644
index 0000000..d64b78a
--- /dev/null
+++ b/src/runtime/na-object-item-fn.h
@@ -0,0 +1,69 @@
+/*
+ * 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 __NA_OBJECT_ITEM_FN_H__
+#define __NA_OBJECT_ITEM_FN_H__
+
+/**
+ * SECTION: na_object_item
+ * @short_description: #NAObjectItem public function declarations.
+ * @include: runtime/na-object-fn.h
+ *
+ * Define here the public functions of the #NAObjectItem class.
+ *
+ * Note that most users of the class should rather use macros defined
+ * in na-object-api.h
+ */
+
+#include "na-object-item-class.h"
+#include "na-iio-provider.h"
+
+G_BEGIN_DECLS
+
+gchar         *na_object_item_get_tooltip( const NAObjectItem *item );
+gchar         *na_object_item_get_icon( const NAObjectItem *item );
+NAIIOProvider *na_object_item_get_provider( const NAObjectItem *item );
+gboolean       na_object_item_is_enabled( const NAObjectItem *item );
+NAObject      *na_object_item_get_item( const NAObjectItem *item, const gchar *id );
+GList         *na_object_item_get_items( const NAObjectItem *item );
+guint          na_object_item_get_items_count( const NAObjectItem *item );
+void           na_object_item_free_items( GList *items );
+
+void           na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip );
+void           na_object_item_set_icon( NAObjectItem *item, const gchar *icon_name );
+void           na_object_item_set_enabled( NAObjectItem *item, gboolean enabled );
+void           na_object_item_set_provider( NAObjectItem *item, const NAIIOProvider *provider );
+void           na_object_item_set_items( NAObjectItem *item, GList *items );
+
+void           na_object_item_append_item( NAObjectItem *item, const NAObject *object );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_ITEM_FN_H__ */
diff --git a/src/runtime/na-object-item.c b/src/runtime/na-object-item.c
new file mode 100644
index 0000000..a6f0c0c
--- /dev/null
+++ b/src/runtime/na-object-item.c
@@ -0,0 +1,910 @@
+/*
+ * Nautilus ObjectItems
+ * A Nautilus extension which offers configurable context menu object_items.
+ *
+ * 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 <string.h>
+#include <uuid/uuid.h>
+
+#include "na-iduplicable.h"
+#include "na-object-api.h"
+#include "na-utils.h"
+
+/* private class data
+ */
+struct NAObjectItemClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectItemPrivate {
+	gboolean       dispose_has_run;
+
+	/* object_item properties
+	 */
+	gchar         *tooltip;
+	gchar         *icon;
+	gboolean       enabled;
+
+	/* list of NAObjectId subitems
+	 */
+	GList         *items;
+
+	/* the original provider
+	 * required to be able to edit/delete the item
+	 */
+	NAIIOProvider *provider;
+};
+
+/* object properties
+ */
+enum {
+	NAOBJECT_ITEM_PROP_TOOLTIP_ID = 1,
+	NAOBJECT_ITEM_PROP_ICON_ID,
+	NAOBJECT_ITEM_PROP_ENABLED_ID,
+	NAOBJECT_ITEM_PROP_PROVIDER_ID,
+	NAOBJECT_ITEM_PROP_ITEMS_ID
+};
+
+#define NAOBJECT_ITEM_PROP_TOOLTIP		"na-object-item-tooltip"
+#define NAOBJECT_ITEM_PROP_ICON			"na-object-item-icon"
+#define NAOBJECT_ITEM_PROP_ENABLED		"na-object-item-enabled"
+#define NAOBJECT_ITEM_PROP_PROVIDER		"na-object-item-provider"
+#define NAOBJECT_ITEM_PROP_ITEMS		"na-object-item-items"
+
+static NAObjectIdClass *st_parent_class = NULL;
+
+static GType    register_type( void );
+static void     class_init( NAObjectItemClass *klass );
+static void     instance_init( GTypeInstance *instance, gpointer klass );
+static void     instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void     instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void     instance_dispose( GObject *object );
+static void     instance_finalize( GObject *object );
+
+static void     object_dump( const NAObject *object );
+static void     object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *object );
+static GList   *object_get_childs( const NAObject *object );
+
+static gchar   *object_id_new_id( const NAObjectId *object, const NAObjectId *new_parent );
+
+GType
+na_object_item_get_type( void )
+{
+	static GType object_type = 0;
+
+	if( !object_type ){
+		object_type = register_type();
+	}
+
+	return( object_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_object_item_register_type";
+
+	static GTypeInfo info = {
+		sizeof( NAObjectItemClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NAObjectItem ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	return( g_type_register_static( NA_OBJECT_ID_TYPE, "NAObjectItem", &info, 0 ));
+}
+
+static void
+class_init( NAObjectItemClass *klass )
+{
+	static const gchar *thisfn = "na_object_item_class_init";
+	GObjectClass *object_class;
+	NAObjectClass *naobject_class;
+	NAObjectIdClass *objectid_class;
+	GParamSpec *spec;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+	object_class->set_property = instance_set_property;
+	object_class->get_property = instance_get_property;
+
+	spec = g_param_spec_string(
+			NAOBJECT_ITEM_PROP_TOOLTIP,
+			"Item tooltip",
+			"Context menu tooltip of the item", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_TOOLTIP_ID, spec );
+
+	spec = g_param_spec_string(
+			NAOBJECT_ITEM_PROP_ICON,
+			"Icon name",
+			"Context menu displayable icon for the item", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_ICON_ID, spec );
+
+	spec = g_param_spec_boolean(
+			NAOBJECT_ITEM_PROP_ENABLED,
+			"Enabled",
+			"Whether this item, and recursively its subitems, is/are enabled", TRUE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_ENABLED_ID, spec );
+
+	spec = g_param_spec_pointer(
+			NAOBJECT_ITEM_PROP_PROVIDER,
+			"Original provider",
+			"Original provider of the NAObjectItem",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_PROVIDER_ID, spec );
+
+	klass->private = g_new0( NAObjectItemClassPrivate, 1 );
+
+	naobject_class = NA_OBJECT_CLASS( klass );
+	naobject_class->dump = object_dump;
+	naobject_class->new = NULL;
+	naobject_class->copy = object_copy;
+	naobject_class->are_equal = object_are_equal;
+	naobject_class->is_valid = object_is_valid;
+	naobject_class->get_childs = object_get_childs;
+
+	objectid_class = NA_OBJECT_ID_CLASS( klass );
+	objectid_class->new_id = object_id_new_id;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	/*static const gchar *thisfn = "na_object_item_instance_init";*/
+	NAObjectItem *self;
+
+	/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+	g_return_if_fail( NA_IS_OBJECT_ITEM( instance ));
+	self = NA_OBJECT_ITEM( instance );
+
+	self->private = g_new0( NAObjectItemPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+
+	/* initialize suitable default values
+	 */
+	self->private->tooltip = g_strdup( "" );
+	self->private->icon = g_strdup( "" );
+	self->private->enabled = TRUE;
+	self->private->provider = NULL;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	NAObjectItem *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+	self = NA_OBJECT_ITEM( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAOBJECT_ITEM_PROP_TOOLTIP_ID:
+				g_value_set_string( value, self->private->tooltip );
+				break;
+
+			case NAOBJECT_ITEM_PROP_ICON_ID:
+				g_value_set_string( value, self->private->icon );
+				break;
+
+			case NAOBJECT_ITEM_PROP_ENABLED_ID:
+				g_value_set_boolean( value, self->private->enabled );
+				break;
+
+			case NAOBJECT_ITEM_PROP_PROVIDER_ID:
+				g_value_set_pointer( value, self->private->provider );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+	NAObjectItem *self;
+
+	g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+	self = NA_OBJECT_ITEM( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAOBJECT_ITEM_PROP_TOOLTIP_ID:
+				g_free( self->private->tooltip );
+				self->private->tooltip = g_value_dup_string( value );
+				break;
+
+			case NAOBJECT_ITEM_PROP_ICON_ID:
+				g_free( self->private->icon );
+				self->private->icon = g_value_dup_string( value );
+				break;
+
+			case NAOBJECT_ITEM_PROP_ENABLED_ID:
+				self->private->enabled = g_value_get_boolean( value );
+				break;
+
+			case NAOBJECT_ITEM_PROP_PROVIDER_ID:
+				self->private->provider = g_value_get_pointer( value );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_item_instance_dispose";*/
+	NAObjectItem *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+	self = NA_OBJECT_ITEM( object );
+
+	if( !self->private->dispose_has_run ){
+
+		na_object_item_free_items( self->private->items );
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_item_instance_finalize";*/
+	NAObjectItem *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+	self = NA_OBJECT_ITEM( object );
+
+	g_free( self->private->tooltip );
+	g_free( self->private->icon );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * na_object_item_get_tooltip:
+ * @item: the #NAObjectItem object to be requested.
+ *
+ * Returns the tooltip which will be display in the Nautilus context
+ * menu item for this @item.
+ *
+ * Returns: the tooltip of the @item as a newly allocated string. This
+ * returned string must be g_free() by the caller.
+ */
+gchar *
+na_object_item_get_tooltip( const NAObjectItem *item )
+{
+	gchar *tooltip = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+
+	if( !item->private->dispose_has_run ){
+		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_TOOLTIP, &tooltip, NULL );
+	}
+
+	return( tooltip );
+}
+
+/**
+ * na_object_item_get_icon:
+ * @item: the #NAObjectItem object to be requested.
+ *
+ * Returns the name of the icon attached to the Nautilus context menu
+ * item for this @item.
+ *
+ * Returns: the icon name as a newly allocated string. This returned
+ * string must be g_free() by the caller.
+ */
+gchar *
+na_object_item_get_icon( const NAObjectItem *item )
+{
+	gchar *icon = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+
+	if( !item->private->dispose_has_run ){
+		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ICON, &icon, NULL );
+	}
+
+	return( icon );
+}
+
+/**
+ * na_object_item_get_provider:
+ * @item: the #NAObjectItem object to be requested.
+ *
+ * Returns the initial provider of the item (or the last which has
+ * accepted a write operation). At the time of this request, this is
+ * the most probable provider willing to accept a next writing
+ * operation.
+ *
+ * Returns: a #NAIIOProvider object. The reference is
+ * owned by #NAPivot pivot and should not be g_object_unref() by the
+ * caller.
+ */
+NAIIOProvider *
+na_object_item_get_provider( const NAObjectItem *item )
+{
+	NAIIOProvider *provider = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+
+	if( !item->private->dispose_has_run ){
+		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_PROVIDER, &provider, NULL );
+	}
+
+	return( provider );
+}
+
+/**
+ * na_object_item_get_item:
+ * @item: the #NAObjectItem from which we want retrieve a subitem.
+ * @id: the id of the searched subitem.
+ *
+ * Returns: a pointer to the #NAObject subitem with the required id.
+ *
+ * The returned #NAObject is owned by the @item object ; the
+ * caller should not try to g_free() nor g_object_unref() it.
+ */
+NAObject *
+na_object_item_get_item( const NAObjectItem *item, const gchar *id )
+{
+	GList *it;
+	NAObject *found = NULL;
+	NAObject *isub;
+	gchar *isubid;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+
+	if( !item->private->dispose_has_run ){
+
+		for( it = item->private->items ; it && !found ; it = it->next ){
+			isub = NA_OBJECT( it->data );
+			isubid = na_object_get_id( isub );
+			if( !strcmp( id, isubid )){
+				found = isub;
+			}
+			g_free( isubid );
+		}
+	}
+
+	return( found );
+}
+
+/**
+ * na_object_item_get_items:
+ * @item: the #NAObjectItem from which we want a list of subitems.
+ *
+ * Returns: a newly allocated #GList of #NAObject objects which are
+ * embedded in the @item. Depending of the exact nature of @item, these
+ * may be #NAObjectMenu, #NAObjectAction or #NAObjectProfile subitems.
+ *
+ * The returned pointer should be na_object_item_free_items() or
+ * na_object_free_items() by the caller.
+ */
+GList *
+na_object_item_get_items( const NAObjectItem *item )
+{
+	GList *items = NULL;
+	GList *it;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+
+	if( !item->private->dispose_has_run ){
+
+		for( it = item->private->items ; it ; it = it->next ){
+			items = g_list_prepend( items, g_object_ref( it->data ));
+		}
+
+		items = g_list_reverse( items );
+	}
+
+	return( items );
+}
+
+/**
+ * na_object_item_get_items_count:
+ * @item: the #NAObjectItem from which we want a count of subitems.
+ *
+ * Returns: the count of subitems of @item.
+ */
+guint
+na_object_item_get_items_count( const NAObjectItem *item )
+{
+	guint count = 0;
+
+	/*g_debug( "na_object_item_get_items_count: item=%p (%s)", ( void * ) item, G_OBJECT_TYPE_NAME( item ));*/
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), 0 );
+
+	if( !item->private->dispose_has_run ){
+		count = item->private->items ? g_list_length( item->private->items ) : 0;
+	}
+
+	return( count );
+}
+
+/**
+ * na_object_item_free_items:
+ * @list: a list of #NAObject subitems as returned by
+ * na_object_item_get_items().
+ *
+ * Frees the list.
+ */
+void
+na_object_item_free_items( GList *items )
+{
+	GList *it;
+
+	for( it = items ; it ; it = it->next ){
+		if( G_IS_OBJECT( it->data )){
+			g_object_unref( it->data );
+		/*} else {
+			g_warning( "na_object_item_free_items: %p not an object", ( void * ) it->data );*/
+		}
+	}
+
+	g_list_free( items );
+}
+
+/**
+ * na_object_item_is_enabled:
+ * @item: the #NAObjectItem object to be requested.
+ *
+ * Is the specified item enabled ?
+ * When disabled, the item, not its subitems if any, is/are never
+ * candidate to any selection.
+ *
+ * Returns: %TRUE if the item is enabled, %FALSE else.
+ */
+gboolean
+na_object_item_is_enabled( const NAObjectItem *item )
+{
+	gboolean enabled = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
+
+	if( !item->private->dispose_has_run ){
+		g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ENABLED, &enabled, NULL );
+	}
+
+	return( enabled );
+}
+
+/**
+ * na_object_item_set_tooltip:
+ * @item: the #NAObjectItem object to be updated.
+ * @tooltip: the tooltip to be set.
+ *
+ * Sets a new tooltip for the @item. Tooltip will be displayed by
+ * Nautilus when the user move its mouse over the Nautilus context menu
+ * item.
+ *
+ * #NAObjectItem takes a copy of the provided tooltip. This later may
+ * so be g_free() by the caller after this function returns.
+ */
+void
+na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip )
+{
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+
+	if( !item->private->dispose_has_run ){
+		g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_TOOLTIP, tooltip, NULL );
+	}
+}
+
+/**
+ * na_object_item_set_icon:
+ * @item: the #NAObjectItem object to be updated.
+ * @icon: the icon name to be set.
+ *
+ * Sets a new icon name for the @item.
+ *
+ * #NAObjectItem takes a copy of the provided icon name. This later may
+ * so be g_free() by the caller after this function returns.
+ */
+void
+na_object_item_set_icon( NAObjectItem *item, const gchar *icon )
+{
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+
+	if( !item->private->dispose_has_run ){
+		g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ICON, icon, NULL );
+	}
+}
+
+/**
+ * na_object_item_set_enabled:
+ * @item: the #NAObjectItem object to be updated.
+ * @enabled: the indicator to be set.
+ *
+ * Sets whether the item, and its subitems if any, is/are enabled or not.
+ */
+void
+na_object_item_set_enabled( NAObjectItem *item, gboolean enabled )
+{
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+
+	if( !item->private->dispose_has_run ){
+		g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ENABLED, enabled, NULL );
+	}
+}
+
+/**
+ * na_object_item_set_provider:
+ * @item: the #NAObjectItem object to be updated.
+ * @provider: the #NAIIOProvider to be set.
+ *
+ * Sets the I/O provider for this #NAObjectItem.
+ */
+void
+na_object_item_set_provider( NAObjectItem *item, const NAIIOProvider *provider )
+{
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+
+	if( !item->private->dispose_has_run ){
+		g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_PROVIDER, provider, NULL );
+	}
+}
+
+/**
+ * na_object_item_set_items:
+ * @item: the #NAObjectItem whose subitems have to be set.
+ * @list: a #GList list of #NAObject subitems to be installed.
+ *
+ * Sets the list of the subitems for the @item.
+ *
+ * The previously existing list is removed and replaced by the provided
+ * one. As we create here a new list with a new reference on provided
+ * subitems, the provided list can be safely na_object_items_free_items()
+ * by the caller.
+ */
+void
+na_object_item_set_items( NAObjectItem *item, GList *items )
+{
+	GList *it;
+
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+
+	if( !item->private->dispose_has_run ){
+
+		na_object_item_free_items( item->private->items );
+		item->private->items = NULL;
+
+		for( it = items ; it ; it = it->next ){
+			item->private->items = g_list_prepend( item->private->items, g_object_ref( it->data ));
+		}
+
+		item->private->items = g_list_reverse( item->private->items );
+	}
+}
+
+/**
+ * na_object_item_append_item:
+ * @item: the #NAObjectItem to which add the subitem.
+ * @object: a #NAObject to be added to list of subitems.
+ *
+ * Appends a new @object to the list of subitems of @item.
+ *
+ * Doesn't modify the reference count on @object.
+ */
+void
+na_object_item_append_item( NAObjectItem *item, const NAObject *object )
+{
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+	g_return_if_fail( NA_IS_OBJECT( object ));
+
+	if( !item->private->dispose_has_run ){
+
+		if( !g_list_find( item->private->items, ( gpointer ) object )){
+			item->private->items = g_list_append( item->private->items, ( gpointer ) object );
+		}
+	}
+}
+
+static void
+object_dump( const NAObject *item )
+{
+	static const gchar *thisfn = "na_object_item_object_dump";
+
+	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+
+	if( !NA_OBJECT_ITEM( item )->private->dispose_has_run ){
+
+		g_debug( "%s:  tooltip='%s'", thisfn, NA_OBJECT_ITEM( item )->private->tooltip );
+		g_debug( "%s:     icon='%s'", thisfn, NA_OBJECT_ITEM( item )->private->icon );
+		g_debug( "%s:  enabled='%s'", thisfn, NA_OBJECT_ITEM( item )->private->enabled ? "True" : "False" );
+		g_debug( "%s: provider=%p", thisfn, ( void * ) NA_OBJECT_ITEM( item )->private->provider );
+
+		/* dump subitems */
+		g_debug( "%s: %d subitem(s) at %p",
+				thisfn,
+				NA_OBJECT_ITEM( item )->private->items ? g_list_length( NA_OBJECT_ITEM( item )->private->items ) : 0,
+				( void * ) NA_OBJECT_ITEM( item )->private->items );
+
+		/* do not recurse here, as this is actually dealt with by
+		 * na_object_dump() api ; else, we would have the action body
+		 * being dumped after its childs
+		 */
+	}
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+	gchar *tooltip, *icon;
+	gboolean enabled;
+	gpointer provider;
+	GList *subitems, *it;
+
+	g_return_if_fail( NA_IS_OBJECT_ITEM( target ));
+	g_return_if_fail( NA_IS_OBJECT_ITEM( source ));
+
+	if( !NA_OBJECT_ITEM( target )->private->dispose_has_run &&
+		!NA_OBJECT_ITEM( source )->private->dispose_has_run ){
+
+		g_object_get( G_OBJECT( source ),
+				NAOBJECT_ITEM_PROP_TOOLTIP, &tooltip,
+				NAOBJECT_ITEM_PROP_ICON, &icon,
+				NAOBJECT_ITEM_PROP_ENABLED, &enabled,
+				NAOBJECT_ITEM_PROP_PROVIDER, &provider,
+				NULL );
+
+		g_object_set( G_OBJECT( target ),
+				NAOBJECT_ITEM_PROP_TOOLTIP, tooltip,
+				NAOBJECT_ITEM_PROP_ICON, icon,
+				NAOBJECT_ITEM_PROP_ENABLED, enabled,
+				NAOBJECT_ITEM_PROP_PROVIDER, provider,
+				NULL );
+
+		g_free( tooltip );
+		g_free( icon );
+
+		subitems = NULL;
+		for( it = NA_OBJECT_ITEM( source )->private->items ; it ; it = it->next ){
+			subitems = g_list_prepend( subitems, na_object_duplicate( it->data ));
+		}
+		subitems = g_list_reverse( subitems );
+		na_object_set_items( target, subitems );
+		na_object_free_items( subitems );
+	}
+}
+
+/*
+ * @a: original object.
+ * @b: the object which has been initially duplicated from @a, and is
+ * being checked for modification status.
+ *
+ * note 1: The provider is not considered as pertinent here
+ *
+ * note 2: as a particular case, this function is not recursive
+ * because the equality test will stop as soon as it fails, and we so
+ * cannot be sure to even come here.
+ *
+ * The recursivity of na_object_check_edition_status() is directly
+ * dealt with by the main entry api function.
+ *
+ * More, the modification status of subitems doesn't have any
+ * impact on this object itself, provided that subitems lists are
+ * themselves identical
+ *
+ * note 3: #NAObjectAction is considered as modified when at least one
+ * of the profiles is itself modified (because they are saved as a
+ * whole). See #NAObjectAction.
+ */
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+	gboolean equal = TRUE;
+	GList *it;
+	gchar *first_id, *second_id;
+	NAObject *first_obj, *second_obj;
+	gint first_pos, second_pos;
+	GList *second_list;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( a ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( b ), FALSE );
+
+	if( !NA_OBJECT_ITEM( a )->private->dispose_has_run &&
+		!NA_OBJECT_ITEM( b )->private->dispose_has_run ){
+
+		if( equal ){
+			equal =
+				( g_utf8_collate( NA_OBJECT_ITEM( a )->private->tooltip, NA_OBJECT_ITEM( b )->private->tooltip ) == 0 ) &&
+				( g_utf8_collate( NA_OBJECT_ITEM( a )->private->icon, NA_OBJECT_ITEM( b )->private->icon ) == 0 );
+		}
+
+		if( equal ){
+			equal = ( NA_OBJECT_ITEM( a )->private->enabled && NA_OBJECT_ITEM( b )->private->enabled ) ||
+					( !NA_OBJECT_ITEM( a )->private->enabled && !NA_OBJECT_ITEM( b )->private->enabled );
+		}
+
+		if( equal ){
+			equal = ( g_list_length( NA_OBJECT_ITEM( a )->private->items ) == g_list_length( NA_OBJECT_ITEM( b )->private->items ));
+		}
+
+		if( equal ){
+			for( it = NA_OBJECT_ITEM( a )->private->items ; it && equal ; it = it->next ){
+				first_id = na_object_get_id( it->data );
+				second_obj = na_object_get_item( b, first_id );
+				if( second_obj ){
+					first_pos = g_list_position( NA_OBJECT_ITEM( a )->private->items, it );
+					second_list = g_list_find( NA_OBJECT_ITEM( b )->private->items, second_obj );
+					second_pos = g_list_position( NA_OBJECT_ITEM( b )->private->items, second_list );
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+					g_debug( "na_object_item_object_are_equal: first_pos=%u, second_pos=%u", first_pos, second_pos );
+#endif
+					if( first_pos != second_pos ){
+						equal = FALSE;
+					}
+				} else {
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+					g_debug( "na_object_item_object_are_equal: id=%s not found in b", first_id );
+#endif
+					equal = FALSE;
+				}
+				g_free( first_id );
+			}
+		}
+
+		if( equal ){
+			for( it = NA_OBJECT_ITEM( b )->private->items ; it && equal ; it = it->next ){
+				second_id = na_object_get_id( it->data );
+				first_obj = na_object_get_item( a, second_id );
+				if( !first_obj ){
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+					g_debug( "na_object_item_object_are_equal: id=%s not found in a", second_id );
+#endif
+					equal = FALSE;
+				}
+				g_free( second_id );
+			}
+		}
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+		g_debug( "na_object_item_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+				( void * ) a, G_OBJECT_TYPE_NAME( a ),
+				( void * ) b, G_OBJECT_TYPE_NAME( b ),
+				equal ? "True":"False" );
+#endif
+	}
+
+	return( equal );
+}
+
+/*
+ * from NAObjectItem point of view, all objects are valid
+ */
+static gboolean
+object_is_valid( const NAObject *object )
+{
+	gboolean valid = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( object ), FALSE );
+
+	if( !NA_OBJECT_ITEM( object )->private->dispose_has_run ){
+
+		/* nothing to check here */
+	}
+
+	return( valid );
+}
+
+static GList *
+object_get_childs( const NAObject *object )
+{
+	GList *childs = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( object ), NULL );
+
+	if( !NA_OBJECT_ITEM( object )->private->dispose_has_run ){
+		childs = NA_OBJECT_ITEM( object )->private->items;
+	}
+
+	return( childs );
+}
+
+/*
+ * new_parent is not relevant when allocating a new UUID for an action
+ * or a menu ; it may safely be left as NULL though there is no gain to
+ * check this
+ */
+static gchar *
+object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent )
+{
+	GList *it;
+	uuid_t uuid;
+	gchar uuid_str[64];
+	gchar *new_uuid = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+
+	if( !NA_OBJECT_ITEM( item )->private->dispose_has_run ){
+
+		/* recurse into NAObjectItems childs
+		 * i.e., if a menu, recurse into embedded actions
+		 */
+		if( NA_OBJECT_ITEM( item )->private->items &&
+			NA_IS_OBJECT_ITEM( NA_OBJECT_ITEM( item )->private->items->data )){
+
+			for( it = NA_OBJECT_ITEM( item )->private->items ; it ; it = it->next ){
+				na_object_set_new_id( it->data, new_parent );
+			}
+		}
+
+		uuid_generate( uuid );
+		uuid_unparse_lower( uuid, uuid_str );
+		new_uuid = g_strdup( uuid_str );
+	}
+
+	return( new_uuid );
+}
diff --git a/src/runtime/na-object-menu-class.h b/src/runtime/na-object-menu-class.h
new file mode 100644
index 0000000..89b5ea6
--- /dev/null
+++ b/src/runtime/na-object-menu-class.h
@@ -0,0 +1,73 @@
+/*
+ * 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 __NA_OBJECT_MENU_CLASS_H__
+#define __NA_OBJECT_MENU_CLASS_H__
+
+/**
+ * SECTION: na_object_menu
+ * @short_description: #NAObjectMenu class definition.
+ * @include: runtime/na-object-menu.h
+ *
+ * This is a menu. It embeds other menus and/or actions.
+ */
+
+#include "na-object-item-class.h"
+
+G_BEGIN_DECLS
+
+#define NA_OBJECT_MENU_TYPE					( na_object_menu_get_type())
+#define NA_OBJECT_MENU( object )			( G_TYPE_CHECK_INSTANCE_CAST( object, NA_OBJECT_MENU_TYPE, NAObjectMenu ))
+#define NA_OBJECT_MENU_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NA_OBJECT_MENU_TYPE, NAObjectMenuClass ))
+#define NA_IS_OBJECT_MENU( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_OBJECT_MENU_TYPE ))
+#define NA_IS_OBJECT_MENU_CLASS( klass )	( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_OBJECT_MENU_TYPE ))
+#define NA_OBJECT_MENU_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_OBJECT_MENU_TYPE, NAObjectMenuClass ))
+
+typedef struct NAObjectMenuPrivate NAObjectMenuPrivate;
+
+typedef struct {
+	NAObjectItem         parent;
+	NAObjectMenuPrivate *private;
+}
+	NAObjectMenu;
+
+typedef struct NAObjectMenuClassPrivate NAObjectMenuClassPrivate;
+
+typedef struct {
+	NAObjectItemClass         parent;
+	NAObjectMenuClassPrivate *private;
+}
+	NAObjectMenuClass;
+
+GType         na_object_menu_get_type( void );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_MENU_CLASS_H__ */
diff --git a/src/common/na-gconf-keys-base.h b/src/runtime/na-object-menu-fn.h
similarity index 62%
rename from src/common/na-gconf-keys-base.h
rename to src/runtime/na-object-menu-fn.h
index 5ebc0d8..2311155 100644
--- a/src/common/na-gconf-keys-base.h
+++ b/src/runtime/na-object-menu-fn.h
@@ -28,16 +28,30 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_GCONF_KEYS_BASE_H__
-#define __NA_GCONF_KEYS_BASE_H__
+#ifndef __NA_OBJECT_MENU_FN_H__
+#define __NA_OBJECT_MENU_FN_H__
 
-/* GConf general information
+/**
+ * SECTION: na_object_menu
+ * @short_description: #NAObjectMenu class definition.
+ * @include: runtime/na-object-menu.h
  *
- * They are used both:
- * - by GConf as a NAIIOProvider
- * - by GConf as the preferences storage system
- * - for providing schemas in import/export actions
+ * This is a menu. It embeds other menus and/or actions.
  */
-#define NAUTILUS_ACTIONS_GCONF_BASEDIR			"/apps/nautilus-actions"
 
-#endif /* __NA_GCONF_KEYS_BASE_H__ */
+#include "na-object-menu-class.h"
+
+G_BEGIN_DECLS
+
+/* i18n: default label for a newly created menu */
+#define NA_OBJECT_MENU_DEFAULT_LABEL	_( "New Nautilus menu" )
+
+NAObjectMenu *na_object_menu_new( void );
+
+GSList       *na_object_menu_get_items_list( const NAObjectMenu *menu );
+GSList       *na_object_menu_rebuild_items_list( const NAObjectMenu *menu );
+void          na_object_menu_set_items_list( NAObjectMenu *menu, GSList *items );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_MENU_FN_H__ */
diff --git a/src/runtime/na-object-menu.c b/src/runtime/na-object-menu.c
new file mode 100644
index 0000000..295178e
--- /dev/null
+++ b/src/runtime/na-object-menu.c
@@ -0,0 +1,362 @@
+/*
+ * 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 "na-object-api.h"
+#include "na-utils.h"
+
+/* private class data
+ */
+struct NAObjectMenuClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectMenuPrivate {
+	gboolean dispose_has_run;
+
+	/* this is the list of subitems as a list of id strings
+	 * as readen from IIOProviders
+	 */
+	GSList  *items_ids;
+};
+
+static NAObjectClass *st_parent_class = NULL;
+
+static GType     register_type( void );
+static void      class_init( NAObjectMenuClass *klass );
+static void      instance_init( GTypeInstance *instance, gpointer klass );
+static void      instance_dispose( GObject *object );
+static void      instance_finalize( GObject *object );
+
+static void      object_dump( const NAObject *menu );
+static NAObject *object_new( const NAObject *menu );
+static void      object_copy( NAObject *target, const NAObject *source );
+static gboolean  object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean  object_is_valid( const NAObject *menu );
+
+GType
+na_object_menu_get_type( void )
+{
+	static GType action_type = 0;
+
+	if( !action_type ){
+		action_type = register_type();
+	}
+
+	return( action_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_object_menu_register_type";
+
+	static GTypeInfo info = {
+		sizeof( NAObjectMenuClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NAObjectMenu ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	return( g_type_register_static( NA_OBJECT_ITEM_TYPE, "NAObjectMenu", &info, 0 ));
+}
+
+static void
+class_init( NAObjectMenuClass *klass )
+{
+	static const gchar *thisfn = "na_object_menu_class_init";
+	GObjectClass *object_class;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NAObjectMenuClassPrivate, 1 );
+
+	NA_OBJECT_CLASS( klass )->dump = object_dump;
+	NA_OBJECT_CLASS( klass )->new = object_new;
+	NA_OBJECT_CLASS( klass )->copy = object_copy;
+	NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
+	NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
+	NA_OBJECT_CLASS( klass )->get_childs = NULL;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	/*static const gchar *thisfn = "na_object_menu_instance_init";*/
+	NAObjectMenu *self;
+
+	/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+	g_return_if_fail( NA_IS_OBJECT_MENU( instance ));
+	self = NA_OBJECT_MENU( instance );
+
+	self->private = g_new0( NAObjectMenuPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_menu_instance_dispose";*/
+	NAObjectMenu *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_MENU( object ));
+	self = NA_OBJECT_MENU( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_menu_instance_finalize";*/
+	NAObjectMenu *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_MENU( object ));
+	self = NA_OBJECT_MENU( object );
+
+	/* release string list of subitems */
+	na_utils_free_string_list( self->private->items_ids );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * na_object_menu_new:
+ *
+ * Allocates a new #NAObjectMenu object.
+ *
+ * The new #NAObjectMenu object is initialized with suitable default values,
+ * but without any profile.
+ *
+ * Returns: the newly allocated #NAObjectMenu object.
+ */
+NAObjectMenu *
+na_object_menu_new( void )
+{
+	NAObjectMenu *menu;
+
+	menu = g_object_new( NA_OBJECT_MENU_TYPE, NULL );
+
+	na_object_set_new_id( menu, NULL );
+	na_object_set_label( menu, NA_OBJECT_MENU_DEFAULT_LABEL );
+
+	return( menu );
+}
+
+/**
+ * na_object_menu_get_items_list:
+ * @menu: this #NAObjectMenu object.
+ *
+ * Returns: the items_ids string list, as readen from the IIOProvider.
+ *
+ * The returned list should be na_utils_free_string_list() by the caller.
+ */
+GSList *
+na_object_menu_get_items_list( const NAObjectMenu *menu )
+{
+	GSList *list = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_MENU( menu ), NULL );
+
+	if( !menu->private->dispose_has_run ){
+		list = na_utils_duplicate_string_list( menu->private->items_ids );
+	}
+
+	return( list );
+}
+
+/**
+ * na_object_menu_rebuild_items_list:
+ * @menu: this #NAObjectMenu object.
+ *
+ * Returns: a string list which contains the ordered list of ids of
+ * subitems.
+ *
+ * Note that the returned list is built on each call to this function,
+ * and is so an exact image of the current situation.
+ *
+ * The returned list should be na_utils_free_string_list() by the caller.
+ */
+GSList *
+na_object_menu_rebuild_items_list( const NAObjectMenu *menu )
+{
+	GSList *list = NULL;
+	GList *items, *it;
+	gchar *uuid;
+
+	g_return_val_if_fail( NA_IS_OBJECT_MENU( menu ), NULL );
+
+	if( !menu->private->dispose_has_run ){
+
+		items = na_object_get_items( menu );
+
+		for( it = items ; it ; it = it->next ){
+			NAObjectItem *item = NA_OBJECT_ITEM( it->data );
+			uuid = na_object_get_id( item );
+			list = g_slist_prepend( list, uuid );
+		}
+
+		na_object_free_items( items );
+
+		list = g_slist_reverse( list );
+	}
+
+	return( list );
+}
+
+/**
+ * na_object_menu_set_items_list:
+ * @menu: this #NAObjectMenu object.
+ * @items: an ordered list of UUID of subitems.
+ *
+ * Set the internal list of uuids of subitems.
+ *
+ * This function takes a copy of the provided list. This later may so
+ * be safely released by the caller after this function has returned.
+ */
+void
+na_object_menu_set_items_list( NAObjectMenu *menu, GSList *items )
+{
+	g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
+
+	if( !menu->private->dispose_has_run ){
+
+		na_utils_free_string_list( menu->private->items_ids );
+		menu->private->items_ids = na_utils_duplicate_string_list( items );
+	}
+}
+
+static void
+object_dump( const NAObject *menu )
+{
+	static const gchar *thisfn = "na_object_menu_object_dump";
+	/*NAObjectMenu *self;*/
+
+	g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
+
+	if( !NA_OBJECT_MENU( menu )->private->dispose_has_run ){
+
+		g_debug( "%s: (nothing to dump)", thisfn );
+	}
+}
+
+static NAObject *
+object_new( const NAObject *menu )
+{
+	return( NA_OBJECT( na_object_menu_new()));
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+	g_return_if_fail( NA_IS_OBJECT_MENU( target ));
+	g_return_if_fail( NA_IS_OBJECT_MENU( source ));
+
+	if( !NA_OBJECT_MENU( target )->private->dispose_has_run &&
+		!NA_OBJECT_MENU( source )->private->dispose_has_run ){
+
+		/* nothing to do */
+	}
+}
+
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+	gboolean equal = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_MENU( a ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT_MENU( b ), FALSE );
+
+	if( !NA_OBJECT_MENU( a )->private->dispose_has_run &&
+		!NA_OBJECT_MENU( b )->private->dispose_has_run ){
+
+		/* nothing to compare */
+	}
+
+	return( equal );
+}
+
+/*
+ * a valid NAObjectMenu requires a not null, not empty label
+ * this is checked here as NAObject doesn't have this condition
+ */
+static gboolean
+object_is_valid( const NAObject *menu )
+{
+	gchar *label;
+	gboolean is_valid = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_MENU( menu ), FALSE );
+
+	if( !NA_OBJECT_MENU( menu )->private->dispose_has_run ){
+
+		if( is_valid ){
+			label = na_object_get_label( menu );
+			is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
+			g_free( label );
+		}
+	}
+
+	return( is_valid );
+}
diff --git a/src/common/na-object-profile-class.h b/src/runtime/na-object-profile-class.h
similarity index 98%
rename from src/common/na-object-profile-class.h
rename to src/runtime/na-object-profile-class.h
index dd421c8..ce1af23 100644
--- a/src/common/na-object-profile-class.h
+++ b/src/runtime/na-object-profile-class.h
@@ -34,7 +34,7 @@
 /**
  * SECTION: na_object_profile
  * @short_description: #NAObjectProfile class definition.
- * @include: common/na-object-profile-class.h
+ * @include: runtime/na-object-profile-class.h
  *
  * This is a companion class of NAObjectAction. It embeds the profile
  * definition of an action.
diff --git a/src/runtime/na-object-profile-fn.h b/src/runtime/na-object-profile-fn.h
new file mode 100644
index 0000000..1e3699f
--- /dev/null
+++ b/src/runtime/na-object-profile-fn.h
@@ -0,0 +1,86 @@
+/*
+ * 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 __NA_OBJECT_PROFILE_FN_H__
+#define __NA_OBJECT_PROFILE_FN_H__
+
+/**
+ * SECTION: na_object_profile
+ * @short_description: #NAObjectProfile public function declarations.
+ * @include: runtime/na-object-profile.h
+ */
+
+#include <glib/gi18n.h>
+
+#include "na-object-action-class.h"
+#include "na-object-profile-class.h"
+
+G_BEGIN_DECLS
+
+/* internal identifier of profiles must begin with the following prefix
+ * this let us identify a profile key versus an action key
+ * corollarily, no action entry must begin with this same prefix
+ */
+#define OBJECT_PROFILE_PREFIX				"profile-"
+
+/* i18n: default label for a newly created profile */
+#define NA_OBJECT_PROFILE_DEFAULT_LABEL		_( "New profile" )
+
+NAObjectProfile *na_object_profile_new( void );
+
+NAObjectAction  *na_object_profile_get_action( const NAObjectProfile *profile );
+gchar           *na_object_profile_get_path( const NAObjectProfile *profile );
+gchar           *na_object_profile_get_parameters( const NAObjectProfile *profile );
+GSList          *na_object_profile_get_basenames( const NAObjectProfile *profile );
+gboolean         na_object_profile_get_matchcase( const NAObjectProfile *profile );
+GSList          *na_object_profile_get_mimetypes( const NAObjectProfile *profile );
+gboolean         na_object_profile_get_is_file( const NAObjectProfile *profile );
+gboolean         na_object_profile_get_is_dir( const NAObjectProfile *profile );
+gboolean         na_object_profile_get_multiple( const NAObjectProfile *profile );
+GSList          *na_object_profile_get_schemes( const NAObjectProfile *profile );
+
+void             na_object_profile_set_action( NAObjectProfile *profile, const NAObjectAction *action );
+void             na_object_profile_set_path( NAObjectProfile *profile, const gchar *path );
+void             na_object_profile_set_parameters( NAObjectProfile *profile, const gchar *parameters );
+void             na_object_profile_set_basenames( NAObjectProfile *profile, GSList *basenames );
+void             na_object_profile_set_matchcase( NAObjectProfile *profile, gboolean matchcase );
+void             na_object_profile_set_mimetypes( NAObjectProfile *profile, GSList *mimetypes );
+void             na_object_profile_set_isfile( NAObjectProfile *profile, gboolean isfile );
+void             na_object_profile_set_isdir( NAObjectProfile *profile, gboolean isdir );
+void             na_object_profile_set_isfiledir( NAObjectProfile *profile, gboolean isfile, gboolean isdir );
+void             na_object_profile_set_multiple( NAObjectProfile *profile, gboolean multiple );
+void             na_object_profile_set_schemes( NAObjectProfile *profile, GSList *schemes );
+
+gboolean         na_object_profile_is_candidate( const NAObjectProfile *profile, GList *files );
+gchar           *na_object_profile_parse_parameters( const NAObjectProfile *profile, GList *files );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_PROFILE_FN_H__ */
diff --git a/src/runtime/na-object-profile.c b/src/runtime/na-object-profile.c
new file mode 100644
index 0000000..ee9af2e
--- /dev/null
+++ b/src/runtime/na-object-profile.c
@@ -0,0 +1,1601 @@
+/*
+ * 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 <string.h>
+
+#include <libnautilus-extension/nautilus-file-info.h>
+
+#include "na-iduplicable.h"
+#include "na-object-api.h"
+#include "na-gnome-vfs-uri.h"
+#include "na-utils.h"
+
+/* private class data
+ */
+struct NAObjectProfileClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectProfilePrivate {
+	gboolean        dispose_has_run;
+
+	/* the NAObjectAction object
+	 */
+	NAObjectAction *action;
+
+	/* profile properties
+	 */
+	gchar          *path;
+	gchar          *parameters;
+	GSList         *basenames;
+	gboolean        match_case;
+	GSList         *mimetypes;
+	gboolean        is_file;
+	gboolean        is_dir;
+	gboolean        accept_multiple;
+	GSList         *schemes;
+};
+
+/* profile properties
+ */
+enum {
+	NAPROFILE_PROP_ACTION_ID = 1,
+	NAPROFILE_PROP_PATH_ID,
+	NAPROFILE_PROP_PARAMETERS_ID,
+	NAPROFILE_PROP_BASENAMES_ID,
+	NAPROFILE_PROP_MATCHCASE_ID,
+	NAPROFILE_PROP_MIMETYPES_ID,
+	NAPROFILE_PROP_ISFILE_ID,
+	NAPROFILE_PROP_ISDIR_ID,
+	NAPROFILE_PROP_ACCEPT_MULTIPLE_ID,
+	NAPROFILE_PROP_SCHEMES_ID
+};
+
+#define NAPROFILE_PROP_ACTION				"na-profile-action"
+#define NAPROFILE_PROP_PATH					"na-profile-path"
+#define NAPROFILE_PROP_PARAMETERS			"na-profile-parameters"
+#define NAPROFILE_PROP_BASENAMES			"na-profile-basenames"
+#define NAPROFILE_PROP_MATCHCASE			"na-profile-matchcase"
+#define NAPROFILE_PROP_MIMETYPES			"na-profile-mimetypes"
+#define NAPROFILE_PROP_ISFILE				"na-profile-isfile"
+#define NAPROFILE_PROP_ISDIR				"na-profile-isdir"
+#define NAPROFILE_PROP_ACCEPT_MULTIPLE		"na-profile-accept-multiple"
+#define NAPROFILE_PROP_SCHEMES				"na-profile-schemes"
+
+static NAObjectClass *st_parent_class = NULL;
+
+static GType     register_type( void );
+static void      class_init( NAObjectProfileClass *klass );
+static void      instance_init( GTypeInstance *instance, gpointer klass );
+static void      instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void      instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void      instance_dispose( GObject *object );
+static void      instance_finalize( GObject *object );
+
+static int       validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
+
+static void      object_dump( const NAObject *profile );
+static void      object_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
+static NAObject *object_new( const NAObject *profile );
+static void      object_copy( NAObject *target, const NAObject *source );
+static gboolean  object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean  object_is_valid( const NAObject *profile );
+
+static gchar    *object_id_new_id( const NAObjectId *object, const NAObjectId *new_parent );
+
+GType
+na_object_profile_get_type( void )
+{
+	static GType object_type = 0;
+
+	if( !object_type ){
+		object_type = register_type();
+	}
+
+	return( object_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_object_profile_register_type";
+
+	static GTypeInfo info = {
+		sizeof( NAObjectProfileClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NAObjectProfile ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	return( g_type_register_static( NA_OBJECT_ID_TYPE, "NAObjectProfile", &info, 0 ));
+}
+
+static void
+class_init( NAObjectProfileClass *klass )
+{
+	static const gchar *thisfn = "na_object_profile_class_init";
+	GObjectClass *object_class;
+	GParamSpec *spec;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+	object_class->set_property = instance_set_property;
+	object_class->get_property = instance_get_property;
+
+	spec = g_param_spec_pointer(
+			NAPROFILE_PROP_ACTION,
+			"NAAction attachment",
+			"The NAAction action to which this profile belongs",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_ACTION_ID, spec );
+
+	spec = g_param_spec_string(
+			NAPROFILE_PROP_PATH,
+			"Command path",
+			"Command path", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_PATH_ID, spec );
+
+	spec = g_param_spec_string(
+			NAPROFILE_PROP_PARAMETERS,
+			"Command parameters",
+			"Command parameters", "",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_PARAMETERS_ID, spec );
+
+	spec = g_param_spec_pointer(
+			NAPROFILE_PROP_BASENAMES,
+			"Filenames mask",
+			"Filenames mask",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_BASENAMES_ID, spec );
+
+	spec = g_param_spec_boolean(
+			NAPROFILE_PROP_MATCHCASE,
+			"Match case",
+			"Whether the filenames are case sensitive", TRUE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_MATCHCASE_ID, spec );
+
+	spec = g_param_spec_pointer(
+			NAPROFILE_PROP_MIMETYPES,
+			"Mimetypes",
+			"List of selectable mimetypes",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_MIMETYPES_ID, spec );
+
+	spec = g_param_spec_boolean(
+			NAPROFILE_PROP_ISFILE,
+			"Only files",
+			"Whether apply when only files are selected", TRUE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_ISFILE_ID, spec );
+
+	spec = g_param_spec_boolean(
+			NAPROFILE_PROP_ISDIR,
+			"Only dirs",
+			"Whether apply when only dirs are selected", FALSE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_ISDIR_ID, spec );
+
+	spec = g_param_spec_boolean(
+			NAPROFILE_PROP_ACCEPT_MULTIPLE,
+			"Accept multiple selection",
+			"Whether apply when multiple files or folders are selected", TRUE,
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_ACCEPT_MULTIPLE_ID, spec );
+
+	spec = g_param_spec_pointer(
+			NAPROFILE_PROP_SCHEMES,
+			"Schemes",
+			"list of selectable schemes",
+			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+	g_object_class_install_property( object_class, NAPROFILE_PROP_SCHEMES_ID, spec );
+
+	klass->private = g_new0( NAObjectProfileClassPrivate, 1 );
+
+	NA_OBJECT_CLASS( klass )->dump = object_dump;
+	NA_OBJECT_CLASS( klass )->new = object_new;
+	NA_OBJECT_CLASS( klass )->copy = object_copy;
+	NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
+	NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
+	NA_OBJECT_CLASS( klass )->get_childs = NULL;
+
+	NA_OBJECT_ID_CLASS( klass )->new_id = object_id_new_id;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	/*static const gchar *thisfn = "na_object_profile_instance_init";*/
+	NAObjectProfile *self;
+
+	/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( instance ));
+	self = NA_OBJECT_PROFILE( instance );
+
+	self->private = g_new0( NAObjectProfilePrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+
+	/* initialize suitable default values
+	 */
+	self->private->path = g_strdup( "" );
+	self->private->parameters = g_strdup( "" );
+	self->private->basenames = NULL;
+	self->private->basenames = g_slist_append( self->private->basenames, g_strdup( "*" ));
+	self->private->match_case = TRUE;
+	self->private->mimetypes = NULL;
+	self->private->mimetypes = g_slist_append( self->private->mimetypes, g_strdup( "*/*" ));
+	self->private->is_file = TRUE;
+	self->private->is_dir = FALSE;
+	self->private->accept_multiple = FALSE;
+	self->private->schemes = NULL;
+	self->private->schemes = g_slist_append( self->private->schemes, g_strdup( "file" ));
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	NAObjectProfile *self;
+	GSList *list;
+
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+	self = NA_OBJECT_PROFILE( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAPROFILE_PROP_ACTION_ID:
+				g_value_set_pointer( value, self->private->action );
+				break;
+
+			case NAPROFILE_PROP_PATH_ID:
+				g_value_set_string( value, self->private->path );
+				break;
+
+			case NAPROFILE_PROP_PARAMETERS_ID:
+				g_value_set_string( value, self->private->parameters );
+				break;
+
+			case NAPROFILE_PROP_BASENAMES_ID:
+				list = na_utils_duplicate_string_list( self->private->basenames );
+				g_value_set_pointer( value, list );
+				break;
+
+			case NAPROFILE_PROP_MATCHCASE_ID:
+				g_value_set_boolean( value, self->private->match_case );
+				break;
+
+			case NAPROFILE_PROP_MIMETYPES_ID:
+				list = na_utils_duplicate_string_list( self->private->mimetypes );
+				g_value_set_pointer( value, list );
+				break;
+
+			case NAPROFILE_PROP_ISFILE_ID:
+				g_value_set_boolean( value, self->private->is_file );
+				break;
+
+			case NAPROFILE_PROP_ISDIR_ID:
+				g_value_set_boolean( value, self->private->is_dir );
+				break;
+
+			case NAPROFILE_PROP_ACCEPT_MULTIPLE_ID:
+				g_value_set_boolean( value, self->private->accept_multiple );
+				break;
+
+			case NAPROFILE_PROP_SCHEMES_ID:
+				list = na_utils_duplicate_string_list( self->private->schemes );
+				g_value_set_pointer( value, list );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+	NAObjectProfile *self;
+
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+	self = NA_OBJECT_PROFILE( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case NAPROFILE_PROP_ACTION_ID:
+				self->private->action = g_value_get_pointer( value );
+				break;
+
+			case NAPROFILE_PROP_PATH_ID:
+				g_free( self->private->path );
+				self->private->path = g_value_dup_string( value );
+				break;
+
+			case NAPROFILE_PROP_PARAMETERS_ID:
+				g_free( self->private->parameters );
+				self->private->parameters = g_value_dup_string( value );
+				break;
+
+			case NAPROFILE_PROP_BASENAMES_ID:
+				na_utils_free_string_list( self->private->basenames );
+				self->private->basenames = na_utils_duplicate_string_list( g_value_get_pointer( value ));
+				break;
+
+			case NAPROFILE_PROP_MATCHCASE_ID:
+				self->private->match_case = g_value_get_boolean( value );
+				break;
+
+			case NAPROFILE_PROP_MIMETYPES_ID:
+				na_utils_free_string_list( self->private->mimetypes );
+				self->private->mimetypes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
+				break;
+
+			case NAPROFILE_PROP_ISFILE_ID:
+				self->private->is_file = g_value_get_boolean( value );
+				break;
+
+			case NAPROFILE_PROP_ISDIR_ID:
+				self->private->is_dir = g_value_get_boolean( value );
+				break;
+
+			case NAPROFILE_PROP_ACCEPT_MULTIPLE_ID:
+				self->private->accept_multiple = g_value_get_boolean( value );
+				break;
+
+			case NAPROFILE_PROP_SCHEMES_ID:
+				na_utils_free_string_list( self->private->schemes );
+				self->private->schemes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_profile_instance_dispose";*/
+	NAObjectProfile *self;
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+	self = NA_OBJECT_PROFILE( object );
+
+	if( !self->private->dispose_has_run ){
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_profile_instance_finalize";*/
+	NAObjectProfile *self;
+
+	/*g_debug( "%s: object=%p", thisfn, (void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+	self = NA_OBJECT_PROFILE( object );
+
+	g_free( self->private->path );
+	g_free( self->private->parameters );
+	na_utils_free_string_list( self->private->basenames );
+	na_utils_free_string_list( self->private->mimetypes );
+	na_utils_free_string_list( self->private->schemes );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * na_object_profile_new:
+ *
+ * Allocates a new profile of the given name.
+ *
+ * Returns: the newly allocated #NAObjectProfile profile.
+ */
+NAObjectProfile *
+na_object_profile_new( void )
+{
+	NAObjectProfile *profile = g_object_new( NA_OBJECT_PROFILE_TYPE, NULL );
+
+	na_object_set_id( profile, OBJECT_PROFILE_PREFIX "zero" );
+
+	/* i18n: default label for a new profile */
+	na_object_set_label( profile, NA_OBJECT_PROFILE_DEFAULT_LABEL );
+
+	return( profile );
+}
+
+/**
+ * na_object_profile_get_action:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Returns a pointer to the action to which this profile is attached,
+ * or NULL if the profile has never been attached.
+ *
+ * Returns: a #NAAction pointer.
+ *
+ * Note that the returned #NAAction pointer is owned by the profile.
+ * The caller should not try to g_free() nor g_object_unref() it.
+ */
+NAObjectAction *
+na_object_profile_get_action( const NAObjectProfile *profile )
+{
+	NAObjectAction *action = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ACTION, &action, NULL );
+	}
+
+	return( action );
+}
+
+/**
+ * na_object_profile_get_path:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Returns the path of the command attached to the profile.
+ *
+ * Returns: the command path as a newly allocated string. The returned
+ * string must be g_free() by the caller.
+ */
+gchar *
+na_object_profile_get_path( const NAObjectProfile *profile )
+{
+	gchar *path = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_PATH, &path, NULL );
+	}
+
+	return( path );
+}
+
+/**
+ * na_object_profile_get_parameters:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Returns the parameters of the command attached to the profile.
+ *
+ * Returns: the command parameters as a newly allocated string. The
+ * returned string must be g_free() by the caller.
+ */
+gchar *
+na_object_profile_get_parameters( const NAObjectProfile *profile )
+{
+	gchar *parameters = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_PARAMETERS, &parameters, NULL );
+	}
+
+	return( parameters );
+}
+
+/**
+ * na_object_profile_get_basenames:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Returns the basenames of the files to which the profile applies.
+ *
+ * Returns: a GSList of newly allocated strings. The list must be
+ * na_utils_free_string_list() by the caller.
+ *
+ * See na_object_profile_set_basenames() for some rationale about
+ * basenames.
+ */
+GSList *
+na_object_profile_get_basenames( const NAObjectProfile *profile )
+{
+	GSList *basenames = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_BASENAMES, &basenames, NULL );
+	}
+
+	return( basenames );
+}
+
+/**
+ * na_object_profile_get_matchcase:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Are specified basenames case sensitive ?
+ *
+ * Returns: %TRUE if the provided filenames are case sensitive, %FALSE
+ * else.
+ *
+ * See na_object_profile_set_matchcase() for some rationale about case
+ * sensitivity.
+ */
+gboolean
+na_object_profile_get_matchcase( const NAObjectProfile *profile )
+{
+	gboolean matchcase = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_MATCHCASE, &matchcase, NULL );
+	}
+
+	return( matchcase );
+}
+
+/**
+ * na_object_profile_get_mimetypes:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Returns the list of mimetypes this profile applies to.
+ *
+ * Returns: a GSList of newly allocated strings. The list must be
+ * na_utils_free_string_list() by the caller.
+ *
+ * See na_object_profile_set_mimetypes() for some rationale about
+ * mimetypes.
+ */
+GSList *
+na_object_profile_get_mimetypes( const NAObjectProfile *profile )
+{
+	GSList *mimetypes = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_MIMETYPES, &mimetypes, NULL );
+	}
+
+	return( mimetypes );
+}
+
+/**
+ * na_object_profile_get_is_file:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Does this profile apply if the selection contains files ?
+ *
+ * Returns: %TRUE if it applies, %FALSE else.
+ *
+ * See na_object_profile_set_isfiledir() for some rationale about file
+ * selection.
+ */
+gboolean
+na_object_profile_get_is_file( const NAObjectProfile *profile )
+{
+	gboolean isfile = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ISFILE, &isfile, NULL );
+	}
+
+	return( isfile );
+}
+
+/**
+ * na_object_profile_get_is_dir:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Does this profile apply if the selection contains folders ?
+ *
+ * Returns: %TRUE if it applies, %FALSE else.
+ *
+ * See na_object_profile_set_isfiledir() for some rationale about file
+ * selection.
+ */
+gboolean
+na_object_profile_get_is_dir( const NAObjectProfile *profile )
+{
+	gboolean isdir = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ISDIR, &isdir, NULL );
+	}
+
+	return( isdir );
+}
+
+/**
+ * na_object_profile_get_multiple:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Does this profile apply if selection contains multiple files or
+ * folders ?
+ *
+ * Returns: %TRUE if it applies, %FALSE else.
+ *
+ * See na_object_profile_set_multiple() for some rationale about
+ * multiple selection.
+ */
+gboolean
+na_object_profile_get_multiple( const NAObjectProfile *profile )
+{
+	gboolean multiple = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ACCEPT_MULTIPLE, &multiple, NULL );
+	}
+
+	return( multiple );
+}
+
+/**
+ * na_object_profile_get_schemes:
+ * @profile: the #NAObjectProfile to be requested.
+ *
+ * Returns the list of schemes this profile applies to.
+ *
+ * Returns: a GSList of newly allocated strings. The list must be
+ * na_utils_free_string_list() by the caller.
+ *
+ * See na_object_profile_set_schemes() for some rationale about
+ * schemes.
+ */
+GSList *
+na_object_profile_get_schemes( const NAObjectProfile *profile )
+{
+	GSList *schemes = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( !profile->private->dispose_has_run ){
+		g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_SCHEMES, &schemes, NULL );
+	}
+
+	return( schemes );
+}
+
+/**
+ * na_object_profile_set_action:
+ * @profile: the #NAObjectProfile to be updated.
+ * @action: the #NAAction action to which this profile is attached.
+ *
+ * Sets the action to which this profile is attached.
+ *
+ * The reference count of the @action is not modified.
+ */
+void
+na_object_profile_set_action( NAObjectProfile *profile, const NAObjectAction *action )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+	g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ACTION, action, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_path:
+ * @profile: the #NAObjectProfile to be updated.
+ * @path: the command path to be set.
+ *
+ * Sets the path of the command for this profile.
+ *
+ * #NAObjectProfile takes a copy of the provided path. This later may
+ * so be g_free() by the caller after this function returns.
+ */
+void
+na_object_profile_set_path( NAObjectProfile *profile, const gchar *path )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_PATH, path, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_parameters:
+ * @profile: the #NAObjectProfile to be updated.
+ * @parameters : the command parameters to be set.
+ *
+ * Sets the parameters of the command for this profile.
+ *
+ * #NAObjectProfile takes a copy of the provided parameters. This later
+ * may so be g_free() by the caller after this function returns.
+ */
+void
+na_object_profile_set_parameters( NAObjectProfile *profile, const gchar *parameters )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_PARAMETERS, parameters, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_basenames:
+ * @profile: the #NAObjectProfile to be updated.
+ * @basenames : the basenames to be set.
+ *
+ * Sets the basenames of the elements on which this profile applies.
+ *
+ * #NAObjectProfile takes a copy of the provided basenames. This later
+ * may so be na_utils_free_string_list() by the caller after this
+ * function returns.
+ *
+ * The basenames list defaults to the single element "*", which means
+ * that the profile will apply to all basenames.
+ */
+void
+na_object_profile_set_basenames( NAObjectProfile *profile, GSList *basenames )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_BASENAMES, basenames, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_matchcase:
+ * @profile: the #NAObjectProfile to be updated.
+ * @matchcase : whether the basenames are case sensitive or not.
+ *
+ * Sets the 'match_case' flag, indicating if specified basename
+ * patterns are, or not, case sensitive.
+ *
+ * This value defaults to %TRUE, which means that basename patterns
+ * default to be case sensitive.
+ */
+void
+na_object_profile_set_matchcase( NAObjectProfile *profile, gboolean matchcase )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_MATCHCASE, matchcase, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_mimetypes:
+ * @profile: the #NAObjectProfile to be updated.
+ * @mimetypes: list of mimetypes to be matched.
+ *
+ * Sets the mimetypes on which this profile applies.
+ *
+ * #NAObjectProfile takes a copy of the provided mimetypes. This later
+ * may so be na_utils_free_string_list() by the caller after this
+ * function returns.
+ *
+ * The mimetypes list defaults to the single element "* / *", which
+ * means that the profile will apply to all types of files.
+ */
+void
+na_object_profile_set_mimetypes( NAObjectProfile *profile, GSList *mimetypes )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_MIMETYPES, mimetypes, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_isfile:
+ * @profile: the #NAObjectProfile to be updated.
+ * @isfile: whether the profile applies only to files.
+ *
+ * Sets the 'isfile' flag on which this profile applies.
+ */
+void
+na_object_profile_set_isfile( NAObjectProfile *profile, gboolean isfile )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ISFILE, isfile, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_isdir:
+ * @profile: the #NAObjectProfile to be updated.
+ * @isdir: the profile applies only to folders.
+ *
+ * Sets the 'isdir' flag on which this profile applies.
+ */
+void
+na_object_profile_set_isdir( NAObjectProfile *profile, gboolean isdir )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ISDIR, isdir, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_isfiledir:
+ * @profile: the #NAObjectProfile to be updated.
+ * @isfile: whether the profile applies only to files.
+ * @isdir: the profile applies only to folders.
+ *
+ * Sets the 'isfile' and 'isdir' flags on which this profile applies.
+ *
+ * File selection defaults to %TRUE.
+ *
+ * Folder selection defaults to %FALSE, which means that this profile will
+ * not apply if the selection contains folders.
+ */
+void
+na_object_profile_set_isfiledir( NAObjectProfile *profile, gboolean isfile, gboolean isdir )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ISFILE, isfile, NAPROFILE_PROP_ISDIR, isdir, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_multiple:
+ * @profile: the #NAObjectProfile to be updated.
+ * @multiple: TRUE if it does.
+ *
+ * Sets if this profile accept multiple selection ?
+ *
+ * This value defaults to %FALSE, which means that this profile will
+ * not apply if the selection contains more than one element.
+ */
+void
+na_object_profile_set_multiple( NAObjectProfile *profile, gboolean multiple )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ACCEPT_MULTIPLE, multiple, NULL );
+	}
+}
+
+/**
+ * na_object_profile_set_schemes:
+ * @profile: the #NAObjectProfile to be updated.
+ * @schemes: list of schemes which apply.
+ *
+ * Sets the schemes on which this profile applies.
+ *
+ * #NAObjectProfile takes a copy of the provided mimetypes. This later
+ * may so be na_utils_free_string_list() by the caller after this
+ * function returns.
+ *
+ * The schemes list defaults to the single element "file", which means
+ * that the profile will only apply to local files.
+ */
+void
+na_object_profile_set_schemes( NAObjectProfile *profile, GSList *schemes )
+{
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+	if( !profile->private->dispose_has_run ){
+		g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_SCHEMES, schemes, NULL );
+	}
+}
+
+/**
+ * na_object_profile_is_candidate:
+ * @profile: the #NAObjectProfile to be checked.
+ * @files: the currently selected items, as provided by Nautilus.
+ *
+ * Determines if the given profile is candidate to be displayed in the
+ * Nautilus context menu, regarding the list of currently selected
+ * items.
+ *
+ * Returns: %TRUE if this profile succeeds to all tests and is so a
+ * valid candidate to be displayed in Nautilus context menu, %FALSE
+ * else.
+ *
+ * This method could have been leaved outside of the #NAObjectProfile
+ * class, as it is only called by the plugin. Nonetheless, it is much
+ * more easier to code here (because we don't need all get methods, nor
+ * free the parameters after).
+ */
+gboolean
+na_object_profile_is_candidate( const NAObjectProfile *profile, GList* files )
+{
+	gboolean retv = FALSE;
+	gboolean test_multiple_file = FALSE;
+	gboolean test_file_type = FALSE;
+	gboolean test_scheme = FALSE;
+	gboolean test_basename = FALSE;
+	gboolean test_mimetype = FALSE;
+	GList* glob_patterns = NULL;
+	GList* glob_mime_patterns = NULL;
+	GSList* iter;
+	GList* iter1;
+	GList* iter2;
+	guint dir_count = 0;
+	guint file_count = 0;
+	guint total_count = 0;
+	guint scheme_ok_count = 0;
+	guint glob_ok_count = 0;
+	guint mime_glob_ok_count = 0;
+	gboolean basename_match_ok = FALSE;
+	gboolean mimetype_match_ok = FALSE;
+	gchar *tmp_pattern, *tmp_filename, *tmp_filename2, *tmp_mimetype, *tmp_mimetype2;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+
+	if( profile->private->dispose_has_run ){
+		return( FALSE );
+	}
+
+	if (profile->private->basenames && profile->private->basenames->next != NULL &&
+			g_ascii_strcasecmp ((gchar*)(profile->private->basenames->data), "*") == 0)
+	{
+		/* if the only pattern is '*' then all files will match, so it
+		 * is not necessary to make the test for each of them
+		 */
+		test_basename = TRUE;
+	}
+	else
+	{
+		for (iter = profile->private->basenames; iter; iter = iter->next)
+		{
+			tmp_pattern = (gchar*)iter->data;
+			if (!profile->private->match_case)
+			{
+				/* --> if case-insensitive asked, lower all the string
+				 * since the pattern matching function don't manage it
+				 * itself.
+				 */
+				tmp_pattern = g_ascii_strdown ((gchar*)iter->data, strlen ((gchar*)iter->data));
+			}
+
+			glob_patterns = g_list_append (glob_patterns, g_pattern_spec_new (tmp_pattern));
+
+			if (!profile->private->match_case)
+			{
+				g_free (tmp_pattern);
+			}
+		}
+	}
+
+	if (profile->private->mimetypes && profile->private->mimetypes->next != NULL &&
+			(g_ascii_strcasecmp ((gchar*)(profile->private->mimetypes->data), "*") == 0 ||
+			 g_ascii_strcasecmp ((gchar*)(profile->private->mimetypes->data), "*/*") == 0))
+	{
+		/* if the only pattern is '*' or * / * then all mimetypes will
+		 * match, so it is not necessary to make the test for each of them
+		 */
+		test_mimetype = TRUE;
+	}
+	else
+	{
+		for (iter = profile->private->mimetypes; iter; iter = iter->next)
+		{
+			glob_mime_patterns = g_list_append (glob_mime_patterns, g_pattern_spec_new ((gchar*)iter->data));
+		}
+	}
+
+	for (iter1 = files; iter1; iter1 = iter1->next)
+	{
+		tmp_filename = nautilus_file_info_get_name ((NautilusFileInfo *)iter1->data);
+
+		if (tmp_filename)
+		{
+			tmp_mimetype = nautilus_file_info_get_mime_type ((NautilusFileInfo *)iter1->data);
+
+			if (!profile->private->match_case)
+			{
+				/* --> if case-insensitive asked, lower all the string
+				 * since the pattern matching function don't manage it
+				 * itself.
+				 */
+				tmp_filename2 = g_ascii_strdown (tmp_filename, strlen (tmp_filename));
+				g_free (tmp_filename);
+				tmp_filename = tmp_filename2;
+			}
+
+			/* --> for the moment we deal with all mimetypes case-insensitively */
+			tmp_mimetype2 = g_ascii_strdown (tmp_mimetype, strlen (tmp_mimetype));
+			g_free (tmp_mimetype);
+			tmp_mimetype = tmp_mimetype2;
+
+			if (nautilus_file_info_is_directory ((NautilusFileInfo *)iter1->data))
+			{
+				dir_count++;
+			}
+			else
+			{
+				file_count++;
+			}
+
+			scheme_ok_count += validate_schemes (profile->private->schemes, (NautilusFileInfo*)iter1->data);
+
+			if (!test_basename) /* if it is already ok, skip the test to improve performance */
+			{
+				basename_match_ok = FALSE;
+				iter2 = glob_patterns;
+				while (iter2 && !basename_match_ok)
+				{
+					if (g_pattern_match_string ((GPatternSpec*)iter2->data, tmp_filename))
+					{
+						basename_match_ok = TRUE;
+					}
+					iter2 = iter2->next;
+				}
+
+				if (basename_match_ok)
+				{
+					glob_ok_count++;
+				}
+			}
+
+			if (!test_mimetype) /* if it is already ok, skip the test to improve performance */
+			{
+				mimetype_match_ok = FALSE;
+				iter2 = glob_mime_patterns;
+				while (iter2 && !mimetype_match_ok)
+				{
+					if (g_pattern_match_string ((GPatternSpec*)iter2->data, tmp_mimetype))
+					{
+						mimetype_match_ok = TRUE;
+					}
+					iter2 = iter2->next;
+				}
+
+				if (mimetype_match_ok)
+				{
+					mime_glob_ok_count++;
+				}
+			}
+
+			g_free (tmp_mimetype);
+			g_free (tmp_filename);
+
+		}
+
+		total_count++;
+	}
+
+	if ((files != NULL) && (files->next == NULL) && (!profile->private->accept_multiple))
+	{
+		test_multiple_file = TRUE;
+	}
+	else if (profile->private->accept_multiple)
+	{
+		test_multiple_file = TRUE;
+	}
+
+	if (profile->private->is_dir && profile->private->is_file)
+	{
+		if (dir_count > 0 || file_count > 0)
+		{
+			test_file_type = TRUE;
+		}
+	}
+	else if (profile->private->is_dir && !profile->private->is_file)
+	{
+		if (file_count == 0)
+		{
+			test_file_type = TRUE;
+		}
+	}
+	else if (!profile->private->is_dir && profile->private->is_file)
+	{
+		if (dir_count == 0)
+		{
+			test_file_type = TRUE;
+		}
+	}
+
+	if (scheme_ok_count == total_count)
+	{
+		test_scheme = TRUE;
+	}
+
+
+	if (!test_basename) /* if not already tested */
+	{
+		if (glob_ok_count == total_count)
+		{
+			test_basename = TRUE;
+		}
+	}
+
+	if (!test_mimetype) /* if not already tested */
+	{
+		if (mime_glob_ok_count == total_count)
+		{
+			test_mimetype = TRUE;
+		}
+	}
+
+	if (test_basename && test_mimetype && test_file_type && test_scheme && test_multiple_file)
+	{
+		retv = TRUE;
+	}
+
+	g_list_foreach (glob_patterns, (GFunc) g_pattern_spec_free, NULL);
+	g_list_free (glob_patterns);
+	g_list_foreach (glob_mime_patterns, (GFunc) g_pattern_spec_free, NULL);
+	g_list_free (glob_mime_patterns);
+
+	return retv;
+}
+
+/**
+ * Expands the parameters path, in function of the found tokens.
+ *
+ * @profile: the selected profile.
+ *
+ * @files: the list of currently selected items, as provided by Nautilus.
+ *
+ * Valid parameters are :
+ *
+ * %d : base dir of the (first) selected file(s)/folder(s)
+ * %f : the name of the (first) selected file/folder
+ * %h : hostname of the (first) URI
+ * %m : list of the basename of the selected files/directories separated by space.
+ * %M : list of the selected files/directories with their complete path separated by space.
+ * %p : port number from the (first) URI
+ * %R : space-separated list of URIs
+ * %s : scheme of the (first) URI
+ * %u : (first) URI
+ * %U : username of the (first) URI
+ * %% : a percent sign
+ *
+ * Adding a parameter requires updating of :
+ * - src/common/na/na-action-profile.c:na_object_profile_parse_parameters()
+ * - src/common/na/na-xml-names.h
+ * - src/nact/nact-icommand-tab.c:parse_parameters()
+ * - src/nact/nautilus-actions-config-tool.ui:LegendDialog
+ */
+gchar *
+na_object_profile_parse_parameters( const NAObjectProfile *profile, GList* files )
+{
+	gchar *parsed = NULL;
+	GString *string;
+	GList *ifi;
+	gboolean first;
+	gchar *iuri, *ipath, *ibname;
+	GFile *iloc;
+	gchar *uri = NULL;
+	gchar *scheme = NULL;
+	gchar *dirname = NULL;
+	gchar *filename = NULL;
+	gchar *hostname = NULL;
+	gchar *username = NULL;
+	gint port_number = 0;
+	GString *basename_list, *pathname_list, *uris_list;
+	gchar *tmp, *iter, *old_iter;
+	NAGnomeVFSURI *vfs;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+
+	if( profile->private->dispose_has_run ){
+		return( NULL );
+	}
+
+	string = g_string_new( "" );
+	basename_list = g_string_new( "" );
+	pathname_list = g_string_new( "" );
+	uris_list = g_string_new( "" );
+	first = TRUE;
+
+	for( ifi = files ; ifi ; ifi = ifi->next ){
+
+		iuri = nautilus_file_info_get_uri(( NautilusFileInfo * ) ifi->data );
+		iloc = nautilus_file_info_get_location(( NautilusFileInfo * ) ifi->data );
+		ipath = g_file_get_path( iloc );
+		ibname = g_file_get_basename( iloc );
+
+		if( first ){
+
+			vfs = g_new0( NAGnomeVFSURI, 1 );
+			na_gnome_vfs_uri_parse( vfs, iuri );
+
+			uri = g_strdup( iuri );
+			dirname = g_path_get_dirname( ipath );
+			scheme = nautilus_file_info_get_uri_scheme(( NautilusFileInfo * ) ifi->data );
+			filename = g_strdup( ibname );
+			hostname = g_strdup( vfs->host_name );
+			username = g_strdup( vfs->user_name );
+			port_number = vfs->host_port;
+
+			first = FALSE;
+			na_gnome_vfs_uri_free( vfs );
+		}
+
+		tmp = g_shell_quote( ibname );
+		g_string_append_printf( basename_list, " %s", tmp );
+		g_free( tmp );
+
+		tmp = g_shell_quote( ipath );
+		g_string_append_printf( pathname_list, " %s", tmp );
+		g_free( tmp );
+
+		tmp = g_shell_quote( iuri );
+		g_string_append_printf( uris_list, " %s", tmp );
+		g_free( tmp );
+
+		g_free( ibname );
+		g_free( ipath );
+		g_object_unref( iloc );
+		g_free( iuri );
+	}
+
+	iter = g_strdup( profile->private->parameters );
+	old_iter = iter;
+
+	while(( iter = g_strstr_len( iter, strlen( iter ), "%" ))){
+
+		string = g_string_append_len( string, old_iter, strlen( old_iter ) - strlen( iter ));
+		switch( iter[1] ){
+
+			/* base dir of the (first) selected item
+			 */
+			case 'd':
+				tmp = g_shell_quote( dirname );
+				string = g_string_append( string, tmp );
+				g_free( tmp );
+				break;
+
+			/* basename of the (first) selected item
+			 */
+			case 'f':
+				tmp = g_shell_quote( filename );
+				string = g_string_append( string, tmp );
+				g_free( tmp );
+				break;
+
+			/* hostname of the (first) URI
+			 */
+			case 'h':
+				string = g_string_append( string, hostname );
+				break;
+
+			/* space-separated list of the basenames
+			 */
+			case 'm':
+				string = g_string_append( string, basename_list->str );
+				break;
+
+			/* space-separated list of full pathnames
+			 */
+			case 'M':
+				string = g_string_append( string, pathname_list->str );
+				break;
+
+			/* port number of the (first) URI
+			 */
+			case 'p':
+				if( port_number > 0 ){
+					g_string_append_printf( string, "%d", port_number );
+				}
+				break;
+
+			/* list of URIs
+			 */
+			case 'R':
+				string = g_string_append( string, uris_list->str );
+				break;
+
+			/* scheme of the (first) URI
+			 */
+			case 's':
+				string = g_string_append( string, scheme );
+				break;
+
+			/* URI of the first item
+			 */
+			case 'u':
+				string = g_string_append( string, uri );
+				break;
+
+			/* username of the (first) URI
+			 */
+			case 'U':
+				string = g_string_append( string, username );
+				break;
+
+			/* a percent sign
+			 */
+			case '%':
+				string = g_string_append_c( string, '%' );
+				break;
+		}
+
+		iter += 2;			/* skip the % sign and the character after */
+		old_iter = iter;	/* store the new start of the string */
+	}
+
+	string = g_string_append_len( string, old_iter, strlen( old_iter ));
+
+	g_free( uri );
+	g_free( dirname );
+	g_free( scheme );
+	g_free( hostname );
+	g_free( username );
+	g_free( iter );
+	g_string_free( uris_list, TRUE );
+	g_string_free( basename_list, TRUE );
+	g_string_free( pathname_list, TRUE );
+
+	parsed = g_string_free( string, FALSE );
+	return( parsed );
+}
+
+static int
+validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
+{
+	int retv = 0;
+	GSList* iter;
+	gboolean found = FALSE;
+	gchar *scheme;
+
+	iter = schemes2test;
+	while (iter && !found)
+	{
+		scheme = nautilus_file_info_get_uri_scheme (file);
+
+		if (g_ascii_strncasecmp (scheme, (gchar*)iter->data, strlen ((gchar*)iter->data)) == 0)
+		{
+			found = TRUE;
+			retv = 1;
+		}
+
+		g_free (scheme);
+		iter = iter->next;
+	}
+
+	return retv;
+}
+
+static void
+object_dump( const NAObject *object )
+{
+	static const gchar *thisfn = "na_object_profile_object_dump";
+	NAObjectProfile *self;
+
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+	self = NA_OBJECT_PROFILE( object );
+
+	if( !self->private->dispose_has_run ){
+
+		g_debug( "%s:          action=%p", thisfn, ( void * ) self->private->action );
+		g_debug( "%s:            path='%s'", thisfn, self->private->path );
+		g_debug( "%s:      parameters='%s'", thisfn, self->private->parameters );
+		g_debug( "%s: accept_multiple='%s'", thisfn, self->private->accept_multiple ? "True" : "False" );
+		g_debug( "%s:          is_dir='%s'", thisfn, self->private->is_dir ? "True" : "False" );
+		g_debug( "%s:         is_file='%s'", thisfn, self->private->is_file ? "True" : "False" );
+		g_debug( "%s:      match_case='%s'", thisfn, self->private->match_case ? "True" : "False" );
+		object_dump_list( thisfn, "basenames", self->private->basenames );
+		object_dump_list( thisfn, "mimetypes", self->private->mimetypes );
+		object_dump_list( thisfn, "  schemes", self->private->schemes );
+	}
+}
+
+static void
+object_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
+{
+	gchar *string = na_utils_gslist_to_schema( list );
+	g_debug( "%s:       %s=%s", thisfn, label, string );
+	g_free( string );
+}
+
+static NAObject *
+object_new( const NAObject *profile )
+{
+	return( NA_OBJECT( na_object_profile_new()));
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+	gchar *path, *parameters;
+	gboolean matchcase, isfile, isdir, multiple;
+	GSList *basenames, *mimetypes, *schemes;
+
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( target ));
+	g_return_if_fail( NA_IS_OBJECT_PROFILE( source ));
+
+	if( !NA_OBJECT_PROFILE( target )->private->dispose_has_run &&
+		!NA_OBJECT_PROFILE( source )->private->dispose_has_run ){
+
+		g_object_get( G_OBJECT( source ),
+				NAPROFILE_PROP_PATH, &path,
+				NAPROFILE_PROP_PARAMETERS, &parameters,
+				NAPROFILE_PROP_BASENAMES, &basenames,
+				NAPROFILE_PROP_MATCHCASE, &matchcase,
+				NAPROFILE_PROP_MIMETYPES, &mimetypes,
+				NAPROFILE_PROP_ISFILE, &isfile,
+				NAPROFILE_PROP_ISDIR, &isdir,
+				NAPROFILE_PROP_ACCEPT_MULTIPLE, &multiple,
+				NAPROFILE_PROP_SCHEMES, &schemes,
+				NULL );
+
+		g_object_set( G_OBJECT( target ),
+				NAPROFILE_PROP_PATH, path,
+				NAPROFILE_PROP_PARAMETERS, parameters,
+				NAPROFILE_PROP_BASENAMES, basenames,
+				NAPROFILE_PROP_MATCHCASE, matchcase,
+				NAPROFILE_PROP_MIMETYPES, mimetypes,
+				NAPROFILE_PROP_ISFILE, isfile,
+				NAPROFILE_PROP_ISDIR, isdir,
+				NAPROFILE_PROP_ACCEPT_MULTIPLE, multiple,
+				NAPROFILE_PROP_SCHEMES, schemes,
+				NULL );
+
+		g_free( path );
+		g_free( parameters );
+		na_utils_free_string_list( basenames );
+		na_utils_free_string_list( mimetypes );
+		na_utils_free_string_list( schemes );
+	}
+}
+
+gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+	NAObjectProfile *first = NA_OBJECT_PROFILE( a );
+	NAObjectProfile *second = NA_OBJECT_PROFILE( b );
+	gboolean equal = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( a ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( b ), FALSE );
+
+	if( !NA_OBJECT_PROFILE( a )->private->dispose_has_run &&
+		!NA_OBJECT_PROFILE( b )->private->dispose_has_run ){
+
+		if( equal ){
+			equal =
+				( g_utf8_collate( first->private->path, second->private->path ) == 0 ) &&
+				( g_utf8_collate( first->private->parameters, second->private->parameters ) == 0 );
+		}
+
+		if( equal ){
+			equal = (( first->private->accept_multiple && second->private->accept_multiple ) ||
+					( !first->private->accept_multiple && !second->private->accept_multiple ));
+		}
+
+		if( equal ){
+			equal = (( first->private->is_dir && second->private->is_dir ) ||
+					( !first->private->is_dir && !second->private->is_dir ));
+		}
+
+		if( equal ){
+			equal = (( first->private->is_file && second->private->is_file ) ||
+					( !first->private->is_file && !second->private->is_file ));
+		}
+
+		if( equal ){
+			equal = na_utils_string_lists_are_equal( first->private->basenames, second->private->basenames ) &&
+					na_utils_string_lists_are_equal( first->private->mimetypes, second->private->mimetypes ) &&
+					na_utils_string_lists_are_equal( first->private->schemes, second->private->schemes );
+		}
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+		g_debug( "na_object_profile_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+				( void * ) a, G_OBJECT_TYPE_NAME( a ),
+				( void * ) b, G_OBJECT_TYPE_NAME( b ),
+				equal ? "True":"False" );
+#endif
+	}
+
+	return( equal );
+}
+
+/*
+ * a valid NAObjectProfile requires a not null, not empty label
+ * this is checked here as NAObject doesn't have this condition
+ */
+gboolean
+object_is_valid( const NAObject *profile )
+{
+	gchar *label;
+	gboolean is_valid = TRUE;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+
+	if( !NA_OBJECT_PROFILE( profile )->private->dispose_has_run ){
+
+		if( is_valid ){
+			label = na_object_get_label( profile );
+			is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
+			g_free( label );
+		}
+	}
+
+	return( is_valid );
+}
+
+/*
+ * new_parent is specifically set to be able to allocate a new id for
+ * the current profile into the target parent
+ */
+static gchar *
+object_id_new_id( const NAObjectId *item, const NAObjectId *new_parent )
+{
+	gchar *id = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT_PROFILE( item ), NULL );
+	g_return_val_if_fail( item && NA_IS_OBJECT_ACTION( item ), NULL );
+
+	if( !NA_OBJECT_PROFILE( item )->private->dispose_has_run ){
+
+		id = na_object_action_get_new_profile_name( NA_OBJECT_ACTION( new_parent ));
+	}
+
+	return( id );
+}
diff --git a/src/runtime/na-object.c b/src/runtime/na-object.c
new file mode 100644
index 0000000..8304f5c
--- /dev/null
+++ b/src/runtime/na-object.c
@@ -0,0 +1,662 @@
+/*
+ * 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 <string.h>
+
+#include "na-object-api.h"
+#include "na-iduplicable.h"
+
+/* private class data
+ */
+struct NAObjectClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectPrivate {
+	gboolean dispose_has_run;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType          register_type( void );
+static void           class_init( NAObjectClass *klass );
+static void           iduplicable_iface_init( NAIDuplicableInterface *iface );
+static void           instance_init( GTypeInstance *instance, gpointer klass );
+static void           instance_constructed( GObject *object );
+static void           instance_dispose( GObject *object );
+static void           instance_finalize( GObject *object );
+
+static NAIDuplicable *iduplicable_new( const NAIDuplicable *object );
+static void           iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source );
+static gboolean       iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b );
+static gboolean       iduplicable_is_valid( const NAIDuplicable *object );
+
+static GList         *v_get_childs( const NAObject *object );
+
+static gboolean       are_equal_hierarchy( const NAObject *a, const NAObject *b );
+static void           copy_hierarchy( NAObject *target, const NAObject *source );
+static gboolean       do_are_equal( const NAObject *a, const NAObject *b );
+static void           do_copy( NAObject *target, const NAObject *source );
+static void           do_dump( const NAObject *object );
+static gboolean       do_is_valid( const NAObject *object );
+static void           dump_hierarchy( const NAObject *object );
+static void           dump_tree( GList *tree, gint level );
+static gboolean       is_valid_hierarchy( const NAObject *object );
+static GList         *most_derived_get_childs( const NAObject *object );
+static NAObject      *most_derived_new( const NAObject *object );
+
+GType
+na_object_get_type( void )
+{
+	static GType object_type = 0;
+
+	if( !object_type ){
+		object_type = register_type();
+	}
+
+	return( object_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "na_object_register_type";
+	GType type;
+
+	static GTypeInfo info = {
+		sizeof( NAObjectClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NAObject ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	static const GInterfaceInfo iduplicable_iface_info = {
+		( GInterfaceInitFunc ) iduplicable_iface_init,
+		NULL,
+		NULL
+	};
+
+	g_debug( "%s", thisfn );
+
+	type = g_type_register_static( G_TYPE_OBJECT, "NAObject", &info, 0 );
+
+	g_type_add_interface_static( type, NA_IDUPLICABLE_TYPE, &iduplicable_iface_info );
+
+	return( type );
+}
+
+static void
+class_init( NAObjectClass *klass )
+{
+	static const gchar *thisfn = "na_object_class_init";
+	GObjectClass *object_class;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->constructed = instance_constructed;
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	klass->private = g_new0( NAObjectClassPrivate, 1 );
+
+	klass->dump = do_dump;
+	klass->new = NULL;
+	klass->copy = do_copy;
+	klass->are_equal = do_are_equal;
+	klass->is_valid = do_is_valid;
+	klass->get_childs = NULL;
+}
+
+static void
+iduplicable_iface_init( NAIDuplicableInterface *iface )
+{
+	static const gchar *thisfn = "na_object_iduplicable_iface_init";
+
+	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+	iface->new = iduplicable_new;
+	iface->copy = iduplicable_copy;
+	iface->are_equal = iduplicable_are_equal;
+	iface->is_valid = iduplicable_is_valid;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "na_object_instance_init";
+	NAObject *self;
+
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_CLASS_NAME( klass ), ( void * ) klass );
+	g_return_if_fail( NA_IS_OBJECT( instance ));
+	self = NA_OBJECT( instance );
+
+	self->private = g_new0( NAObjectPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_constructed( GObject *object )
+{
+	/*static const gchar *thisfn = "na_object_instance_constructed";*/
+
+	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+	g_return_if_fail( NA_IS_OBJECT( object ));
+
+	na_iduplicable_init( NA_IDUPLICABLE( object ));
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->constructed ){
+		G_OBJECT_CLASS( st_parent_class )->constructed( object );
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	static const gchar *thisfn = "na_object_instance_dispose";
+	NAObject *self;
+
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+	g_return_if_fail( NA_IS_OBJECT( object ));
+	self = NA_OBJECT( object );
+
+	if( !self->private->dispose_has_run ){
+
+		na_iduplicable_dispose( NA_IDUPLICABLE( object ));
+
+		self->private->dispose_has_run = TRUE;
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *object )
+{
+	NAObject *self;
+
+	g_return_if_fail( NA_IS_OBJECT( object ));
+	self = NA_OBJECT( object );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( object );
+	}
+}
+
+/**
+ * na_object_iduplicable_duplicate:
+ * @object: the #NAObject object to be dumped.
+ *
+ * Exactly duplicates a #NAObject-derived object.
+ *
+ * Returns: the new #NAObject.
+ *
+ *   na_object_duplicate( origin )
+ *   +- na_object_iduplicable_duplicate( origin )
+ *      +- na_iduplicable_duplicate( origin )
+ *         +- dup = v_new( object )
+ *         |  +- interface->new( object)
+ *         |     +- iduplicable_new( object )
+ *         |        +- most_derived_new( object )
+ *         |           +- object_new( ... ) from a derived class
+ *         +- v_copy( dup, origin )
+ *         |  +- interface->copy( dup, origin )
+ *         |     +- iduplicable_copy( target, source )
+ *         |        +- copy_hierarchy( target, source )
+ *         |           +- object_copy( ... ) from each successive derived class
+ *         +- set_origin( dup, origin )
+ *         +- set_modified( dup, FALSE )
+ *         +- set_valid( dup, FALSE )
+ *
+ * Though the interface api is not recursive per se, the implementation
+ * is ; i.e. duplicating a #NAObjectItem also duplicates the whole tree
+ * inside.
+ */
+NAObject *
+na_object_iduplicable_duplicate( const NAObject *object )
+{
+	NAIDuplicable *duplicate = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+	g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
+
+	if( !object->private->dispose_has_run ){
+
+		duplicate = na_iduplicable_duplicate( NA_IDUPLICABLE( object ));
+
+		/*g_debug( "na_object_iduplicable_duplicate: object=%p (%s), duplicate=%p (%s)",
+				( void * ) object, G_OBJECT_TYPE_NAME( object ),
+				( void * ) duplicate, duplicate ? G_OBJECT_TYPE_NAME( duplicate ) : "" );*/
+	}
+
+	/* do not use NA_OBJECT macro as we may return a (valid) NULL value */
+	return(( NAObject * ) duplicate );
+}
+
+/**
+ * na_object_iduplicable_is_modified:
+ * @object: the #NAObject object whose status is requested.
+ *
+ * Returns the current modification status of @object.
+ *
+ * This suppose that @object has been previously duplicated in order
+ * to get benefits provided by the IDuplicable interface.
+ *
+ * This suppose also that the edition status of @object has previously
+ * been checked via na_object_check_edited_status().
+ *
+ * Returns: %TRUE is the provided object has been modified regarding to
+ * the original one, %FALSE else.
+ */
+gboolean
+na_object_iduplicable_is_modified( const NAObject *object )
+{
+	gboolean is_modified = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+
+	if( !object->private->dispose_has_run ){
+		is_modified = na_iduplicable_is_modified( NA_IDUPLICABLE( object ));
+	}
+
+	return( is_modified );
+}
+
+/**
+ * na_object_object_dump:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Dumps via g_debug the actual content of the object.
+ *
+ * The recursivity is dealt with here. If we let #NAObjectItem do this,
+ * the dump of #NAObjectItem-derived object will be splitted, childs
+ * being inserted inside.
+ */
+void
+na_object_object_dump( const NAObject *object )
+{
+	GList *childs, *ic;
+
+	g_return_if_fail( NA_IS_OBJECT( object ));
+
+	if( !object->private->dispose_has_run ){
+
+		na_object_object_dump_norec( object );
+
+		childs = v_get_childs( object );
+		for( ic = childs ; ic ; ic = ic->next ){
+			na_object_object_dump( NA_OBJECT( ic->data ));
+		}
+	}
+}
+
+/**
+ * na_object_object_dump_norec:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Dumps via g_debug the actual content of the object.
+ *
+ * This function is not recursive.
+ */
+void
+na_object_object_dump_norec( const NAObject *object )
+{
+	g_return_if_fail( NA_IS_OBJECT( object ));
+
+	if( !object->private->dispose_has_run ){
+		dump_hierarchy( object );
+	}
+}
+
+/**
+ * na_object_object_dump_tree:
+ * @tree: a hierarchical list of #NAObject-derived objects.
+ *
+ * Outputs a brief, hierarchical dump of the provided list.
+ */
+void
+na_object_object_dump_tree( GList *tree )
+{
+	dump_tree( tree, 0 );
+}
+
+/**
+ * na_object_get_hierarchy:
+ *
+ * Returns the class hierarchy,
+ * from the topmost base class, to the most-derived one.
+ */
+GList *
+na_object_get_hierarchy( const NAObject *object )
+{
+	GList *hierarchy = NULL;
+	GObjectClass *class;
+
+	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+
+	if( !object->private->dispose_has_run ){
+
+		class = G_OBJECT_GET_CLASS( object );
+
+		while( G_OBJECT_CLASS_TYPE( class ) != NA_OBJECT_TYPE ){
+			hierarchy = g_list_prepend( hierarchy, class );
+			class = g_type_class_peek_parent( class );
+		}
+
+		hierarchy = g_list_prepend( hierarchy, class );
+	}
+
+	return( hierarchy );
+}
+
+/**
+ * na_object_free_hierarchy:
+ */
+void
+na_object_free_hierarchy( GList *hierarchy )
+{
+	g_list_free( hierarchy );
+}
+
+static NAIDuplicable *
+iduplicable_new( const NAIDuplicable *object )
+{
+	NAIDuplicable *new_object = NULL;
+
+	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+
+	if( !NA_OBJECT( object )->private->dispose_has_run ){
+		/* do not use NA_IDUPLICABLE macro as we may return a (valid) NULL value */
+		new_object = ( NAIDuplicable * ) most_derived_new( NA_OBJECT( object ));
+	}
+
+	return( new_object );
+}
+
+static void
+iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
+{
+	g_return_if_fail( NA_IS_OBJECT( target ));
+	g_return_if_fail( NA_IS_OBJECT( source ));
+
+	if( !NA_OBJECT( source )->private->dispose_has_run &&
+		!NA_OBJECT( target )->private->dispose_has_run ){
+
+			copy_hierarchy( NA_OBJECT( target ), NA_OBJECT( source ));
+	}
+}
+
+static gboolean
+iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
+{
+	gboolean are_equal = FALSE;
+
+	g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
+
+	if( !NA_OBJECT( a )->private->dispose_has_run &&
+		!NA_OBJECT( b )->private->dispose_has_run ){
+
+		are_equal = are_equal_hierarchy( NA_OBJECT( a ), NA_OBJECT( b ));
+	}
+
+	return( are_equal );
+}
+
+static gboolean
+iduplicable_is_valid( const NAIDuplicable *object )
+{
+	gboolean is_valid = FALSE;
+
+	if( !NA_OBJECT( object )->private->dispose_has_run ){
+		is_valid = is_valid_hierarchy( NA_OBJECT( object ));
+	}
+
+	return( is_valid );
+}
+
+static GList *
+v_get_childs( const NAObject *object ){
+
+	return( most_derived_get_childs( object ));
+}
+
+static gboolean
+are_equal_hierarchy( const NAObject *a, const NAObject *b )
+{
+	gboolean are_equal;
+	GList *hierarchy, *ih;
+
+	are_equal = TRUE;
+	hierarchy = na_object_get_hierarchy( b );
+
+	for( ih = hierarchy ; ih && are_equal ; ih = ih->next ){
+		if( NA_OBJECT_CLASS( ih->data )->are_equal ){
+			are_equal = NA_OBJECT_CLASS( ih->data )->are_equal( a, b );
+		}
+	}
+
+	na_object_free_hierarchy( hierarchy );
+
+	return( are_equal );
+}
+
+static void
+copy_hierarchy( NAObject *target, const NAObject *source )
+{
+	GList *hierarchy, *ih;
+
+	hierarchy = na_object_get_hierarchy( source );
+
+	for( ih = hierarchy ; ih ; ih = ih->next ){
+		if( NA_OBJECT_CLASS( ih->data )->copy ){
+			NA_OBJECT_CLASS( ih->data )->copy( target, source );
+		}
+	}
+
+	na_object_free_hierarchy( hierarchy );
+}
+
+static gboolean
+do_are_equal( const NAObject *a, const NAObject *b )
+{
+	gboolean are_equal;
+
+	/* as there is no data in NAObject, they are considered here as
+	 * equal is both null or both not null
+	 */
+	are_equal = ( a && b ) || ( !a && !b );
+
+#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
+	g_debug( "na_object_do_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+			( void * ) a, G_OBJECT_TYPE_NAME( a ),
+			( void * ) b, G_OBJECT_TYPE_NAME( b ),
+			are_equal ? "True":"False" );
+#endif
+
+	return( are_equal );
+}
+
+static void
+do_copy( NAObject *target, const NAObject *source )
+{
+	/* nothing to do here */
+}
+
+static void
+do_dump( const NAObject *object )
+{
+	static const char *thisfn = "na_object_do_dump";
+
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+
+	na_iduplicable_dump( NA_IDUPLICABLE( object ));
+}
+
+static gboolean
+do_is_valid( const NAObject *object )
+{
+	/* as there is no data in NAObject, it is always valid */
+	return( object ? TRUE : FALSE );
+}
+
+static void
+dump_hierarchy( const NAObject *object )
+{
+	GList *hierarchy, *ih;
+
+	hierarchy = na_object_get_hierarchy( object );
+
+	for( ih = hierarchy ; ih ; ih = ih->next ){
+		if( NA_OBJECT_CLASS( ih->data )->dump ){
+			NA_OBJECT_CLASS( ih->data )->dump( object );
+		}
+	}
+
+	na_object_free_hierarchy( hierarchy );
+}
+
+static void
+dump_tree( GList *tree, gint level )
+{
+	GString *prefix;
+	gint i;
+	GList *subitems, *it;
+	gchar *id;
+	gchar *label;
+
+	prefix = g_string_new( "" );
+	for( i = 0 ; i < level ; ++i ){
+		g_string_append_printf( prefix, "  " );
+	}
+
+	for( it = tree ; it ; it = it->next ){
+		id = na_object_get_id( it->data );
+		label = na_object_get_label( it->data );
+		g_debug( "na_object_dump_tree: %s%p (%s) %s \"%s\"",
+				prefix->str, ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ), id, label );
+		g_free( id );
+		g_free( label );
+
+		if( NA_IS_OBJECT_ITEM( it->data )){
+			subitems = na_object_get_items( it->data );
+			dump_tree( subitems, level+1 );
+			na_object_free_items( subitems );
+		}
+	}
+
+	g_string_free( prefix, TRUE );
+}
+
+static gboolean
+is_valid_hierarchy( const NAObject *object )
+{
+	gboolean is_valid;
+	GList *hierarchy, *ih;
+
+	is_valid = TRUE;
+	hierarchy = na_object_get_hierarchy( object );
+
+	for( ih = hierarchy ; ih && is_valid ; ih = ih->next ){
+		if( NA_OBJECT_CLASS( ih->data )->is_valid ){
+			is_valid = NA_OBJECT_CLASS( ih->data )->is_valid( object );
+		}
+	}
+
+	na_object_free_hierarchy( hierarchy );
+
+	return( is_valid );
+}
+
+static GList *
+most_derived_get_childs( const NAObject *object )
+{
+	GList *childs;
+	GList *hierarchy, *ih;
+	gboolean found;
+
+	found = FALSE;
+	childs = NULL;
+	hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
+
+	for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+		if( NA_OBJECT_CLASS( ih->data )->get_childs ){
+			childs = NA_OBJECT_CLASS( ih->data )->get_childs( object );
+			found = TRUE;
+		}
+	}
+
+	return( childs );
+}
+
+static NAObject *
+most_derived_new( const NAObject *object )
+{
+	NAObject *new_object;
+	GList *hierarchy, *ih;
+	gboolean found;
+
+	found = FALSE;
+	new_object = NULL;
+	hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
+
+	for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+		if( NA_OBJECT_CLASS( ih->data )->new ){
+			new_object = NA_OBJECT_CLASS( ih->data )->new( object );
+			found = TRUE;
+		}
+	}
+
+	na_object_free_hierarchy( hierarchy );
+
+	return( new_object );
+}
diff --git a/src/common/na-pivot.c b/src/runtime/na-pivot.c
similarity index 99%
rename from src/common/na-pivot.c
rename to src/runtime/na-pivot.c
index e68fd33..2a2ad8c 100644
--- a/src/common/na-pivot.c
+++ b/src/runtime/na-pivot.c
@@ -36,7 +36,6 @@
 #include <uuid/uuid.h>
 
 #include "na-object-api.h"
-#include "na-object-item-class.h"
 #include "na-iio-provider.h"
 #include "na-gconf-monitor.h"
 #include "na-gconf-provider.h"
@@ -383,6 +382,10 @@ na_pivot_get_providers( const NAPivot *pivot, GType type )
 void
 na_pivot_free_providers( GList *providers )
 {
+	static const gchar *thisfn = "na_pivot_free_providers";
+
+	g_debug( "%s: providers=%p", thisfn, ( void * ) providers );
+
 	g_list_foreach( providers, ( GFunc ) g_object_unref, NULL );
 	g_list_free( providers );
 }
diff --git a/src/common/na-pivot.h b/src/runtime/na-pivot.h
similarity index 100%
rename from src/common/na-pivot.h
rename to src/runtime/na-pivot.h
diff --git a/src/runtime/na-utils.c b/src/runtime/na-utils.c
new file mode 100644
index 0000000..e65bc0a
--- /dev/null
+++ b/src/runtime/na-utils.c
@@ -0,0 +1,182 @@
+/*
+ * 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 <gio/gio.h>
+#include <glib-object.h>
+#include <string.h>
+
+#include "na-utils.h"
+
+/**
+ * na_utils_duplicate_string_list:
+ * @list: the GSList to be duplicated.
+ *
+ * Returns: a #GSList of strings.
+ *
+ * The returned list should be na_utils_free_string_list() by the caller.
+ */
+GSList *
+na_utils_duplicate_string_list( GSList *list )
+{
+	GSList *duplist = NULL;
+	GSList *it;
+
+	for( it = list ; it != NULL ; it = it->next ){
+		gchar *dupstr = g_strdup(( gchar * ) it->data );
+		duplist = g_slist_prepend( duplist, dupstr );
+	}
+	duplist = g_slist_reverse( duplist );
+
+	return( duplist );
+}
+
+/**
+ * na_utils_find_in_list:
+ * @list: the GSList of strings to be searched.
+ * @str: the searched string.
+ *
+ * Search for a string in a string list.
+ *
+ * Returns: %TRUE if the string has been found in list.
+ */
+gboolean
+na_utils_find_in_list( GSList *list, const gchar *str )
+{
+	GSList *il;
+
+	for( il = list ; il ; il = il->next ){
+		const gchar *istr = ( const gchar * ) il->data;
+		if( !g_utf8_collate( str, istr )){
+			return( TRUE );
+		}
+	}
+
+	return( FALSE );
+}
+
+/**
+ * na_utils_free_string_list:
+ * @list: the GSList to be freed.
+ *
+ * Frees a GSList of strings.
+ */
+void
+na_utils_free_string_list( GSList *list )
+{
+	g_slist_foreach( list, ( GFunc ) g_free, NULL );
+	g_slist_free( list );
+}
+
+/**
+ * na_utils_string_lists_are_equal:
+ * @first: a GSList of strings.
+ * @second: another GSList of strings to be compared with @first.
+ *
+ * Compare two string lists, without regards to the order.
+ *
+ * Returns: %TRUE if the two lists have same content.
+ */
+gboolean
+na_utils_string_lists_are_equal( GSList *first, GSList *second )
+{
+	GSList *il;
+
+	for( il = first ; il ; il = il->next ){
+		const gchar *str = ( const gchar * ) il->data;
+		if( !na_utils_find_in_list( second, str )){
+			return( FALSE );
+		}
+	}
+
+	for( il = second ; il ; il = il->next ){
+		const gchar *str = ( const gchar * ) il->data;
+		if( !na_utils_find_in_list( first, str )){
+			return( FALSE );
+		}
+	}
+
+	return( TRUE );
+}
+
+/**
+ * na_utils_gslist_to_schema:
+ * @list: a list of strings.
+ *
+ * Converts a list of strings to a comma-separated list of strings,
+ * enclosed by brackets (dump format, GConf export format).
+ *
+ * Returns: a newly allocated string which should be g_free() by the caller.
+ */
+gchar *
+na_utils_gslist_to_schema( GSList *list )
+{
+	GSList *ib;
+	gchar *tmp;
+	gchar *text = g_strdup( "" );
+
+	for( ib = list ; ib ; ib = ib->next ){
+		if( strlen( text )){
+			tmp = g_strdup_printf( "%s,", text );
+			g_free( text );
+			text = tmp;
+		}
+		tmp = g_strdup_printf( "%s%s", text, ( gchar * ) ib->data );
+		g_free( text );
+		text = tmp;
+	}
+
+	tmp = g_strdup_printf( "[%s]", text );
+	g_free( text );
+	text = tmp;
+
+	return( text );
+}
+
+/**
+ * na_utils_path_extract_last_dir:
+ * @path: a full path.
+ *
+ * Extracts the last part of a full path.
+ *
+ * Returns: a newly allocated string which should be g_free() by the caller.
+ */
+gchar *
+na_utils_path_extract_last_dir( const gchar *path )
+{
+	gchar **split = g_strsplit( path, "/", -1 );
+	guint count = g_strv_length( split );
+	gchar *lastdir = g_strdup( split[count-1] );
+	g_strfreev( split );
+	return( lastdir );
+}
diff --git a/src/common/na-gconf-keys-schemas.h b/src/runtime/na-utils.h
similarity index 66%
rename from src/common/na-gconf-keys-schemas.h
rename to src/runtime/na-utils.h
index 83b9aff..5e91179 100644
--- a/src/common/na-gconf-keys-schemas.h
+++ b/src/runtime/na-utils.h
@@ -28,13 +28,28 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NA_GCONF_KEYS_SCHEMAS_H__
-#define __NA_GCONF_KEYS_SCHEMAS_H__
+#ifndef __NA_UTILS_H__
+#define __NA_UTILS_H__
 
-#include "na-gconf-keys-base.h"
+#include <glib.h>
 
-/* GConf general information
+G_BEGIN_DECLS
+
+/* some functions to ease the GSList list manipulations
+ */
+GSList  *na_utils_duplicate_string_list( GSList *list );
+gboolean na_utils_find_in_list( GSList *list, const gchar *str );
+void     na_utils_free_string_list( GSList *list );
+gboolean na_utils_string_lists_are_equal( GSList *first, GSList *second );
+
+/* a GSList to a string [aaaa,bbbb,cccc]
  */
-#define NAUTILUS_ACTIONS_GCONF_SCHEMASDIR		"/schemas"
+gchar   *na_utils_gslist_to_schema( GSList *list );
+
+/* path manipulations
+ */
+gchar   *na_utils_path_extract_last_dir( const gchar *path );
+
+G_END_DECLS
 
-#endif /* __NA_GCONF_KEYS_SCHEMAS_H__ */
+#endif /* __NA_UTILS_H__ */
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index fdd0817..70f7359 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -59,7 +59,7 @@ test_parse_uris_SOURCES = \
 	$(NULL)
 
 test_parse_uris_LDADD = \
-	$(top_builddir)/src/common/libnact.la			\
+	$(top_builddir)/src/common/libna-runtime.la		\
 	$(NAUTILUS_ACTIONS_LIBS)						\
 	$(NULL)
 
@@ -68,7 +68,7 @@ test_virtuals_SOURCES = \
 	$(NULL)
 
 test_virtuals_LDADD = \
-	$(top_builddir)/src/common/libnact.la			\
+	$(top_builddir)/src/common/libna-runtime.la		\
 	$(NAUTILUS_ACTIONS_LIBS)						\
 	$(NULL)
 
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
index fb3fec9..cd2d10d 100644
--- a/src/utils/Makefile.am
+++ b/src/utils/Makefile.am
@@ -43,7 +43,8 @@ nautilus_actions_new_SOURCES = \
 	$(NULL)
 
 nautilus_actions_new_LDADD = \
-	$(top_builddir)/src/common/libnact.la			\
+	$(top_builddir)/src/common/libna-common.la		\
+	$(top_builddir)/src/common/libna-runtime.la		\
 	$(NAUTILUS_ACTIONS_LIBS)						\
 	$(NULL)
 
@@ -52,6 +53,7 @@ nautilus_actions_schemas_SOURCES = \
 	$(NULL)
 
 nautilus_actions_schemas_LDADD = \
-	$(top_builddir)/src/common/libnact.la			\
+	$(top_builddir)/src/common/libna-common.la		\
+	$(top_builddir)/src/common/libna-runtime.la		\
 	$(NAUTILUS_ACTIONS_LIBS)						\
 	$(NULL)



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