[nautilus-actions] Full rewrite of writability status of items vs. providers



commit 8622dfbed65b07e40d41cbf19e511701e98d1aad
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sat Jan 30 13:22:04 2010 +0100

    Full rewrite of writability status of items vs. providers

 ChangeLog                                          |   88 ++++
 TODO                                               |   13 +-
 data/nautilus-actions.schemas.in                   |   73 ++-
 doc/io-provider-id                                 |    3 +-
 nautilus-actions/api/na-gconf-monitor.c            |    5 +-
 nautilus-actions/api/na-iio-provider.c             |    8 +-
 nautilus-actions/api/na-iio-provider.h             |   82 ++-
 .../io-provider-desktop/nadp-desktop-file.c        |    5 +-
 .../io-provider-desktop/nadp-desktop-provider.c    |   13 +-
 .../io-provider-desktop/nadp-desktop-provider.h    |    6 +
 nautilus-actions/io-provider-desktop/nadp-read.c   |    6 +-
 nautilus-actions/io-provider-desktop/nadp-write.c  |   95 +++-
 nautilus-actions/io-provider-desktop/nadp-write.h  |    2 +
 .../io-provider-gconf/nagp-gconf-provider.c        |    7 +-
 nautilus-actions/io-provider-gconf/nagp-write.c    |  155 +++---
 nautilus-actions/io-provider-gconf/nagp-write.h    |    2 +-
 nautilus-actions/nact/base-application.c           |   11 +-
 nautilus-actions/nact/base-assistant.c             |    5 +-
 nautilus-actions/nact/base-builder.c               |   13 +-
 nautilus-actions/nact/base-dialog.c                |    5 +-
 nautilus-actions/nact/base-window.c                |    5 +-
 nautilus-actions/nact/nact-application.c           |   13 +-
 nautilus-actions/nact/nact-assistant-export-ask.c  |    5 +-
 nautilus-actions/nact/nact-assistant-export.c      |    5 +-
 nautilus-actions/nact/nact-assistant-import-ask.c  |    5 +-
 nautilus-actions/nact/nact-assistant-import.c      |    5 +-
 nautilus-actions/nact/nact-clipboard.c             |   13 +-
 nautilus-actions/nact/nact-confirm-logout.c        |    5 +-
 nautilus-actions/nact/nact-iaction-tab.c           |  126 ++---
 nautilus-actions/nact/nact-iactions-list-bis.c     |   18 +-
 nautilus-actions/nact/nact-iactions-list.c         |   10 +-
 nautilus-actions/nact/nact-iactions-list.h         |    4 +-
 nautilus-actions/nact/nact-iadvanced-tab.c         |    8 +-
 nautilus-actions/nact/nact-ibackground-tab.c       |   28 +-
 nautilus-actions/nact/nact-icommand-tab.c          |   14 +-
 nautilus-actions/nact/nact-iconditions-tab.c       |   68 ++--
 nautilus-actions/nact/nact-main-menubar.c          |   26 +-
 nautilus-actions/nact/nact-main-statusbar.c        |   65 ++-
 nautilus-actions/nact/nact-main-statusbar.h        |    2 +-
 nautilus-actions/nact/nact-main-tab.h              |    4 +-
 nautilus-actions/nact/nact-main-window.c           |   71 ++--
 nautilus-actions/nact/nact-providers-list.c        |   55 ++-
 nautilus-actions/nact/nact-tree-model-dnd.c        |    9 +-
 nautilus-actions/nact/nact-tree-model.c            |    5 +-
 nautilus-actions/nact/nact-window.c                |   87 +---
 nautilus-actions/nact/nact-window.h                |    2 -
 nautilus-actions/plugin/nautilus-actions.c         |    4 +-
 nautilus-actions/private/na-object-item-fn.h       |   56 +-
 nautilus-actions/private/na-object-item-priv.h     |   23 +-
 nautilus-actions/private/na-object-item.c          |   32 +-
 nautilus-actions/runtime/na-io-provider.c          |  531 ++++++++------------
 nautilus-actions/runtime/na-io-provider.h          |   32 +-
 nautilus-actions/runtime/na-module.c               |   22 +-
 nautilus-actions/runtime/na-pivot.c                |  297 ++++++++---
 nautilus-actions/runtime/na-pivot.h                |   60 +--
 nautilus-actions/utils/nautilus-actions-new.c      |   17 +-
 nautilus-actions/utils/nautilus-actions-run.c      |    4 +-
 57 files changed, 1255 insertions(+), 1078 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index aed95dc..4730faa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,91 @@
+2009-01-30 Pierre Wieser <pwieser trychlos org>
+
+	A full rewriting of the writability of items vs. providers.
+
+	* data/nautilus-actions.schemas.in:
+	Describe 'export-format' and 'io-providers-order' keys.
+	Define 'mandatory/all/locked' key to lock all configuration.
+
+	* doc/io-provider-id: Reserve 'all' special provider_id.
+
+	* nautilus-actions/api/na-gconf-monitor.c
+	* nautilus-actions/io-provider-desktop/nadp-desktop-file.c
+	* nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
+	* nautilus-actions/nact/base-application.c
+	* nautilus-actions/nact/base-assistant.c
+	* nautilus-actions/nact/base-builder.c
+	* nautilus-actions/nact/base-dialog.c
+	* nautilus-actions/nact/base-window.c
+	* nautilus-actions/nact/nact-application.c
+	* nautilus-actions/nact/nact-assistant-export-ask.c
+	* nautilus-actions/nact/nact-assistant-export.c
+	* nautilus-actions/nact/nact-assistant-import-ask.c
+	* nautilus-actions/nact/nact-assistant-import.c
+	* nautilus-actions/nact/nact-clipboard.c
+	* nautilus-actions/nact/nact-confirm-logout.c
+	* nautilus-actions/nact/nact-window.c
+	* nautilus-actions/runtime/na-module.c
+	(instance_init, instance_dispose):
+	Review debug messages formatting.
+
+	* nautilus-actions/api/na-iio-provider.c:
+	* nautilus-actions/api/na-iio-provider.h
+	(is_writable): Removed API.
+	(is_able_to_write): New API.
+	Review operations return codes.
+	Add provider status.
+
+	* nautilus-actions/io-provider-desktop/nadp-desktop-provider.c:
+	* nautilus-actions/io-provider-desktop/nadp-desktop-provider.h:
+	* nautilus-actions/io-provider-desktop/nadp-read.c:
+	* nautilus-actions/io-provider-desktop/nadp-write.c:
+	* nautilus-actions/io-provider-desktop/nadp-write.h:
+	* nautilus-actions/io-provider-gconf/nagp-gconf-provider.c:
+	* nautilus-actions/io-provider-gconf/nagp-write.c:
+	* nautilus-actions/io-provider-gconf/nagp-write.h:
+	Updated to new NAIIOProvider API.
+
+	* nautilus-actions/nact/nact-iaction-tab.c:
+	* nautilus-actions/nact/nact-iactions-list.c:
+	* nautilus-actions/nact/nact-iactions-list.h:
+	* nautilus-actions/nact/nact-iadvanced-tab.c:
+	* nautilus-actions/nact/nact-ibackground-tab.c:
+	* nautilus-actions/nact/nact-icommand-tab.c:
+	* nautilus-actions/nact/nact-iconditions-tab.c:
+	* nautilus-actions/nact/nact-main-menubar.c:
+	* nautilus-actions/nact/nact-main-tab.h:
+	* nautilus-actions/nact/nact-main-window.c:
+	* nautilus-actions/nact/nact-providers-list.c:
+	* nautilus-actions/nact/nact-tree-model-dnd.c:
+	* nautilus-actions/nact/nact-tree-model.c:
+	* nautilus-actions/nact/nact-window.c:
+	* nautilus-actions/nact/nact-window.h:
+	Take advantage of the new global item writability status.
+
+	* nautilus-actions/nact/nact-main-statusbar.c:
+	* nautilus-actions/nact/nact-main-statusbar.h
+	(nact_main_statusbar_set_locked): Display the reason.
+
+	* nautilus-actions/nact/nact-iactions-list-bis.c
+	(nact_iactions_list_bis_list_modified_items):
+	Dump the raw content of the list.
+
+	* nautilus-actions/plugin/nautilus-actions.c (instance_init):
+	* nautilus-actions/runtime/na-pivot.c:
+	* nautilus-actions/runtime/na-pivot.h(na_pivot_new):
+	* nautilus-actions/utils/nautilus-actions-new.c (write_to_gconf):
+	* nautilus-actions/utils/nautilus-actions-run.c (get_action):
+	New na_pivot_new() signature.
+
+	* nautilus-actions/private/na-object-item-fn.h:
+	* nautilus-actions/private/na-object-item-priv.h:
+	* nautilus-actions/private/na-object-item.c:
+	The NAObjectItem now embeds a NAIOProvider pointer.
+
+	* nautilus-actions/runtime/na-io-provider.c:
+	* nautilus-actions/runtime/na-io-provider.h:
+	Load all available and defined I/O providers.
+
 2009-01-27 Pierre Wieser <pwieser trychlos org>
 
 	* nautilus-actions/nact/nact-preferences.ui:
diff --git a/TODO b/TODO
index 0bbd6e1..a9fe9f2 100644
--- a/TODO
+++ b/TODO
@@ -125,10 +125,11 @@
 
 - enhancement.ui: notebook page should be labeled 'Action' or 'Menu' depending of current item
 
-- rationale: when na-gconf is set by an admin as locked, does this really
-  mean that all GConf must be considered as read-only ? Not really. It should
-  rather be considered as GConf actions are read-only. Preferences stay editable.
-  Does the level-zero is a preference (so editable) or a sort of action (ro) !?
-  see the comment in schema.in
+- nact-iactions-list.c: display_label
+  the 'editable' cell property should be set only once, instead of at each redraw
+  and more because we also compute this on selection change
+  what we should do: compute once, and monitor to only change when needed
 
-- review the searches for writable providers and how this property is set and requested
+- use nact_window_get_pivot
+
+- not all objects are disposed
diff --git a/data/nautilus-actions.schemas.in b/data/nautilus-actions.schemas.in
index 7b2af5a..7ee668e 100644
--- a/data/nautilus-actions.schemas.in
+++ b/data/nautilus-actions.schemas.in
@@ -311,23 +311,23 @@ All schemes used by Nautilus can be used here. This only applies when targeting
     <!-- schemas for preferences -->
 
     <schema>
-      <key>/schemas/apps/nautilus-actions/preferences/assistant-esc-quit</key>
+      <key>/schemas/apps/nautilus-actions/preferences/assistant-esc-confirm</key>
       <owner>nautilus-actions</owner>
       <type>bool</type>
       <locale name="C">
-        <short>Whether the Esc key should close the assistants</short>
-        <long>If TRUE, assistant may be closed by hitting the Esc key.</long>
+        <short>Ask for a confirmation when quitting by Esc</short>
+        <long>If TRUE, a confirmation will be requested when quitting an assistant by hitting the Esc key.</long>
       </locale>
       <default>true</default>
     </schema>
 
     <schema>
-      <key>/schemas/apps/nautilus-actions/preferences/assistant-esc-confirm</key>
+      <key>/schemas/apps/nautilus-actions/preferences/assistant-esc-quit</key>
       <owner>nautilus-actions</owner>
       <type>bool</type>
       <locale name="C">
-        <short>Ask for a confirmation when quitting by Esc</short>
-        <long>If TRUE, a confirmation will be requested when quitting an assistant by hitting the Esc key.</long>
+        <short>Whether the Esc key should close the assistants</short>
+        <long>If TRUE, assistant may be closed by hitting the Esc key.</long>
       </locale>
       <default>true</default>
     </schema>
@@ -356,6 +356,22 @@ All schemes used by Nautilus can be used here. This only applies when targeting
     </schema>
 
     <schema>
+      <key>/schemas/apps/nautilus-actions/preferences/export-format</key>
+      <owner>nautilus-actions</owner>
+      <type>string</type>
+      <locale name="C">
+        <short>Preferred export format</short>
+        <long>This is the preferred export format, used as a default when exporting items, or dropping them outside of the application.
+Possible values are:
+- "GConfSchemaV1": this used to be the historical export format. The exported file may later be imported via Import assistant of the Nautilus Actions Configuration Tool, or via the gconftool-2 --import-schema-file command-line tool.
+- "GConfSchemaV2": a lighter while still compatible schema. The exported file may later be imported via Import assistant of the Nautilus Actions Configuration Tool, or via the gconftool-2 --import-schema-file command-line tool.
+- "GConfEntry": this should be the preferred format for newly exported actions. The exported file may later be imported via Import assistant of the Nautilus Actions Configuration Tool, or via the gconftool-2 --load command-line tool.
+- "Ask": the user will be asked at runtime for the format he wishes use.</long>
+      </locale>
+      <default>/tmp</default>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/nautilus-actions/preferences/ibackground-chooser</key>
       <owner>nautilus-actions</owner>
       <type>list</type>
@@ -431,7 +447,7 @@ All schemes used by Nautilus can be used here. This only applies when targeting
       <type>string</type>
       <locale name="C">
         <short>Last import mode choosen by the user</short>
-        <long>Last import mode choosen by the user when he is asked for in import mode. Possible values are :
+        <long>Last import mode choosen by the user when he is asked for in import mode. Possible values are:
 - "NoImport": do not import an action whose UUID already exists,
 - "Renumber": allocate a new UUID if the imported UUID already exists,
 - "Override": override the existing action with the imported one.</long>
@@ -478,6 +494,18 @@ All schemes used by Nautilus can be used here. This only applies when targeting
     </schema>
 
     <schema>
+      <key>/schemas/apps/nautilus-actions/preferences/io-providers-order</key>
+      <owner>nautilus-actions</owner>
+      <type>list</type>
+      <list_type>string</list_type>
+      <locale name="C">
+        <short>I/O providers Write priority</short>
+        <long>The order in which I/O providers are tested when we need to write a new item down to a storage subsystem.</long>
+      </locale>
+      <default>[]</default>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/nautilus-actions/preferences/iprefs-add-about-item</key>
       <owner>nautilus-actions</owner>
       <type>bool</type>
@@ -526,23 +554,23 @@ All schemes used by Nautilus can be used here. This only applies when targeting
     </schema>
 
     <schema>
-      <key>/schemas/apps/nautilus-actions/preferences/iprefs-relabel-menus</key>
+      <key>/schemas/apps/nautilus-actions/preferences/iprefs-relabel-actions</key>
       <owner>nautilus-actions</owner>
       <type>bool</type>
       <locale name="C">
-        <short>Whether menus should be relabeled when pasted or duplicated</short>
-        <long>Whether menus should be relabeled when pasted or duplicated.</long>
+        <short>Whether actions should be relabeled when pasted or duplicated</short>
+        <long>Whether actions should be relabeled when pasted or duplicated.</long>
       </locale>
       <default>true</default>
     </schema>
 
     <schema>
-      <key>/schemas/apps/nautilus-actions/preferences/iprefs-relabel-actions</key>
+      <key>/schemas/apps/nautilus-actions/preferences/iprefs-relabel-menus</key>
       <owner>nautilus-actions</owner>
       <type>bool</type>
       <locale name="C">
-        <short>Whether actions should be relabeled when pasted or duplicated</short>
-        <long>Whether actions should be relabeled when pasted or duplicated.</long>
+        <short>Whether menus should be relabeled when pasted or duplicated</short>
+        <long>Whether menus should be relabeled when pasted or duplicated.</long>
       </locale>
       <default>true</default>
     </schema>
@@ -653,8 +681,19 @@ A default default list is harcoded in nautilus-actions-config-tool, which may be
 	<!-- sysadmin reserved keys -->
 	<!-- these keys are thought to be set as mandatory keys -->
 	<!-- each I/O provider has its own key, identified by the I/O provider internal id. -->
-	<!-- note that level-zero order of items is written as a GConf preference -->
-	<!-- setting the GConf as read-only (locked) will also prevent any reordering of level-zero items -->
+
+    <schema>
+      <key>/schemas/apps/nautilus-actions/mandatory/all/locked</key>
+      <owner>nautilus-actions</owner>
+      <type>bool</type>
+      <locale name="C">
+        <short>Whether the whole configuration is locked</short>
+        <long>The whole configuration must be understood here as the global set and order of menus and actions.
+When this configuration is locked, then the user is no more able to modify nor create or delete any menu or action. All items are read-only.
+As the order of items is also locked, the level zero itself cannot be modified, and the user is unable to reorder the items.</long>
+      </locale>
+      <default>false</default>
+    </schema>
 
     <schema>
       <key>/schemas/apps/nautilus-actions/mandatory/na-gconf/locked</key>
@@ -662,7 +701,7 @@ A default default list is harcoded in nautilus-actions-config-tool, which may be
       <type>bool</type>
       <locale name="C">
         <short>Whether the GConf I/O provider is locked</short>
-        <long>When set to true (most probably as a mandatory key), this prevents all items readen from GConf to being modified in NACT.</long>
+        <long>When set to true (most probably as a mandatory key), this prevents all items, menus and actions, readen from GConf to being modified in NACT.</long>
       </locale>
       <default>false</default>
     </schema>
@@ -673,7 +712,7 @@ A default default list is harcoded in nautilus-actions-config-tool, which may be
       <type>bool</type>
       <locale name="C">
         <short>Whether the Desktop I/O provider is locked</short>
-        <long>When set to true (most probably as a mandatory key), this prevents all items readen as .desktop files to being modified in NACT.</long>
+        <long>When set to true (most probably as a mandatory key), this prevents all items, menus and actions, readen from .desktop files to being modified in NACT.</long>
       </locale>
       <default>false</default>
     </schema>
diff --git a/doc/io-provider-id b/doc/io-provider-id
index 8f0fa9a..f9e654f 100644
--- a/doc/io-provider-id
+++ b/doc/io-provider-id
@@ -9,5 +9,6 @@ id          label                   holder            allocated
 ----------  ----------------------  ----------------  ----------
 na-desktop  NA Desktop IO Provider  Nautilus-Actions  2009-12-16
 na-gconf    NA GConf IO Provider    Nautilus-Actions  2009-12-16
+all         reserved id             Nautilus-Actions  2010-01-28
 
-Last updated: 2009, Dec. 16th.
+Last updated: 2010, Jan. 28th
diff --git a/nautilus-actions/api/na-gconf-monitor.c b/nautilus-actions/api/na-gconf-monitor.c
index 8284fc4..dda34c1 100644
--- a/nautilus-actions/api/na-gconf-monitor.c
+++ b/nautilus-actions/api/na-gconf-monitor.c
@@ -123,7 +123,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "na_gconf_monitor_instance_init";
 	NAGConfMonitor *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NA_IS_GCONF_MONITOR( instance ));
 	self = NA_GCONF_MONITOR( instance );
 
@@ -136,7 +137,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "na_gconf_monitor_instance_dispose";
 	NAGConfMonitor *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NA_IS_GCONF_MONITOR( object ));
 	self = NA_GCONF_MONITOR( object );
 
diff --git a/nautilus-actions/api/na-iio-provider.c b/nautilus-actions/api/na-iio-provider.c
index 8e7edcc..e398c6f 100644
--- a/nautilus-actions/api/na-iio-provider.c
+++ b/nautilus-actions/api/na-iio-provider.c
@@ -48,7 +48,7 @@ static void     interface_base_init( NAIIOProviderInterface *klass );
 static void     interface_base_finalize( NAIIOProviderInterface *klass );
 
 static gboolean do_is_willing_to_write( const NAIIOProvider *instance );
-static gboolean do_is_writable( const NAIIOProvider *instance, const NAObjectItem *item );
+static gboolean do_is_able_to_write( const NAIIOProvider *instance );
 
 /**
  * Registers the GType of this interface.
@@ -106,7 +106,7 @@ interface_base_init( NAIIOProviderInterface *klass )
 		klass->get_version = NULL;
 		klass->read_items = NULL;
 		klass->is_willing_to_write = do_is_willing_to_write;
-		klass->is_writable = do_is_writable;
+		klass->is_able_to_write = do_is_able_to_write;
 		klass->write_item = NULL;
 		klass->delete_item = NULL;
 
@@ -136,7 +136,7 @@ do_is_willing_to_write( const NAIIOProvider *instance )
 }
 
 static gboolean
-do_is_writable( const NAIIOProvider *instance, const NAObjectItem *item )
+do_is_able_to_write( const NAIIOProvider *instance )
 {
 	return( FALSE );
 }
@@ -150,7 +150,7 @@ do_is_writable( const NAIIOProvider *instance, const NAObjectItem *item )
  * detected a modification in one of its configurations (menu or action).
  *
  * This function should be triggered for each and every #NAObjectItem-
- * derived modified objects, but only once for each one.
+ * derived modified objects, but (if possible) only once for each one.
  */
 void
 na_iio_provider_config_changed( const NAIIOProvider *instance, const gchar *id )
diff --git a/nautilus-actions/api/na-iio-provider.h b/nautilus-actions/api/na-iio-provider.h
index 163c627..e89a436 100644
--- a/nautilus-actions/api/na-iio-provider.h
+++ b/nautilus-actions/api/na-iio-provider.h
@@ -109,7 +109,7 @@ typedef struct {
 	 *
 	 * Reads the whole items list from the specified I/O provider.
 	 *
-	 * Returns: a unordered flat #GList of NAObjectItem-derived objects
+	 * Returns: a unordered flat #GList of #NAObjectItem-derived objects
 	 * (menus or actions) ; the actions embed their own profiles.
 	 */
 	GList *  ( *read_items )         ( const NAIIOProvider *instance, GSList **messages );
@@ -118,34 +118,47 @@ typedef struct {
 	 * is_willing_to_write:
 	 * @instance: the #NAIIOProvider provider.
 	 *
-	 * Checks for global writability of the I/O provider.
+	 * Returns: %TRUE if this I/O provider is willing to write,
+	 *  %FALSE else.
 	 *
-	 * Returns: %TRUE if we are able to update/write/delete a #NAObjectItem
-	 * (menu or action) into this I/O provider, %FALSE else.
+	 * The 'willing_to_write' property is intrinsic to the I/O provider.
+	 * It shouldn't do any supposition against the actual runtime
+	 * environment.
+	 * It just says that the developer/maintainer has released the needed
+	 * code in order to update/create/delete #NAObjectItem-derived objects.
 	 *
-	 * Note that the I/O provider may return a positive writability
-	 * flag when considering the whole I/O storage subsystem, while not
-	 * being able to update/write/delete a particular item
-	 * (see is_writable function below).
-	 *
-	 * Note also that, even if the I/O provider is willing to write,
-	 * a sysadmin may have locked down it, by putting a 'true' value
-	 * in the key '/apps/nautilus-actions/mandatory/<provider_id>/locked'
-	 * (see na_io_provider_is_willing_to_write).
+	 * Note that even if this property is %TRUE, there is yet several
+	 * reasons for not being able to update/delete existing items or
+	 * create new ones (see e.g. #is_able_to_write() below).
 	 */
 	gboolean ( *is_willing_to_write )( const NAIIOProvider *instance );
 
 	/**
-	 * is_writable:
+	 * is_able_to_write:
 	 * @instance: the #NAIIOProvider provider.
-	 * @item: a #NAObjectItem-derived menu or action.
 	 *
-	 * Checks for writability of this particular @item.
+	 * Returns: %TRUE if this I/O provider is able to do write
+	 * operations at runtime, %FALSE else.
+	 *
+	 * The 'able_to_write' property is a runtime one.
+	 * When returning %TRUE, the I/O provider insures that it has
+	 * sucessfully checked that it was able to write some things
+	 * down to its storage subsystems.
+	 *
+	 * The 'able_to_write' property is independant of the
+	 * 'willing_to_write' above.
+	 *
+	 * This condition is only relevant when trying to define new items,
+	 * to see if a willing_to provider is actually able to do write
+	 * operations. It it not relevant for updating/deleting already
+	 * existings items as they have already checked their own runtime
+	 * writability status when readen from the storage subsystems.
 	 *
-	 * Returns: %TRUE if we are able to update/write/delete the
-	 * @item, %FALSE else.
+	 * Note that even if this property is %TRUE, there is yet several
+	 * reasons for not being able to update/delete existing items or
+	 * create new ones (see e.g. #is_willing_to_write() above).
 	 */
-	gboolean ( *is_writable )        ( const NAIIOProvider *instance, const NAObjectItem *item );
+	gboolean ( *is_able_to_write )   ( const NAIIOProvider *instance );
 
 	/**
 	 * write_item:
@@ -191,15 +204,32 @@ GType na_iio_provider_get_type       ( void );
  */
 void  na_iio_provider_config_changed ( const NAIIOProvider *instance, const gchar *id );
 
-/* return code of write/delete operations
+/* the reasons for which an item may not be writable
+ * adding a new status here should imply also adding a new tooltip
+ * in nact_main_statusbar_set_locked().
+ */
+enum {
+	NA_IIO_PROVIDER_STATUS_UNDETERMINED = 0,
+	NA_IIO_PROVIDER_STATUS_WRITABLE,
+	NA_IIO_PROVIDER_STATUS_ITEM_READONLY,
+	NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO,
+	NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND,
+	NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_ADMIN,
+	NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_USER,
+	NA_IIO_PROVIDER_STATUS_CONFIGURATION_LOCKED_BY_ADMIN,
+	NA_IIO_PROVIDER_STATUS_NO_API,
+	NA_IIO_PROVIDER_STATUS_LAST,
+};
+
+/* return code of operations
  */
 enum {
-	NA_IIO_PROVIDER_WRITE_OK = 0,
-	NA_IIO_PROVIDER_NOT_WRITABLE,
-	NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE,
-	NA_IIO_PROVIDER_WRITE_ERROR,
-	NA_IIO_PROVIDER_NO_PROVIDER,
-	NA_IIO_PROVIDER_PROGRAM_ERROR
+	NA_IIO_PROVIDER_CODE_OK = 0,
+	NA_IIO_PROVIDER_CODE_PROGRAM_ERROR = 1 + NA_IIO_PROVIDER_STATUS_LAST,
+	NA_IIO_PROVIDER_CODE_NOT_WILLING_TO_RUN,
+	NA_IIO_PROVIDER_CODE_WRITE_ERROR,
+	NA_IIO_PROVIDER_CODE_DELETE_SCHEMAS_ERROR,
+	NA_IIO_PROVIDER_CODE_DELETE_CONFIG_ERROR,
 };
 
 G_END_DECLS
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-file.c b/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
index e8b5fa4..25bbdef 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-file.c
@@ -124,7 +124,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nadp_desktop_file_instance_init";
 	NadpDesktopFile *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NADP_IS_DESKTOP_FILE( instance ));
 	self = NADP_DESKTOP_FILE( instance );
 
@@ -140,7 +141,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "nadp_desktop_file_instance_dispose";
 	NadpDesktopFile *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NADP_IS_DESKTOP_FILE( object ));
 	self = NADP_DESKTOP_FILE( object );
 
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
index 0bd3655..33149b9 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.c
@@ -47,12 +47,6 @@ struct NadpDesktopProviderClassPrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
-/* private instance data
- */
-struct NadpDesktopProviderPrivate {
-	gboolean dispose_has_run;
-};
-
 static GType         st_module_type = 0;
 static GObjectClass *st_parent_class = NULL;
 
@@ -131,7 +125,7 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
 	iface->get_version = get_version;
 	iface->read_items = nadp_iio_provider_read_items;
 	iface->is_willing_to_write = nadp_iio_provider_is_willing_to_write;
-	iface->is_writable = nadp_iio_provider_is_writable;
+	iface->is_able_to_write = nadp_iio_provider_is_able_to_write;
 	iface->write_item = nadp_iio_provider_write_item;
 	iface->delete_item = nadp_iio_provider_delete_item;
 }
@@ -142,7 +136,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nadp_desktop_provider_instance_init";
 	NadpDesktopProvider *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( instance ));
 	self = NADP_DESKTOP_PROVIDER( instance );
 
@@ -157,7 +152,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "nadp_desktop_provider_instance_dispose";
 	NadpDesktopProvider *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NADP_IS_DESKTOP_PROVIDER( object ));
 	self = NADP_DESKTOP_PROVIDER( object );
 
diff --git a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h
index 8ee5560..61548d4 100644
--- a/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h
+++ b/nautilus-actions/io-provider-desktop/nadp-desktop-provider.h
@@ -57,6 +57,12 @@ G_BEGIN_DECLS
 
 typedef struct NadpDesktopProviderPrivate NadpDesktopProviderPrivate;
 
+/* private instance data
+ */
+struct NadpDesktopProviderPrivate {
+	gboolean dispose_has_run;
+};
+
 typedef struct {
 	GObject                     parent;
 	NadpDesktopProviderPrivate *private;
diff --git a/nautilus-actions/io-provider-desktop/nadp-read.c b/nautilus-actions/io-provider-desktop/nadp-read.c
index a56c0dc..6d2039e 100644
--- a/nautilus-actions/io-provider-desktop/nadp-read.c
+++ b/nautilus-actions/io-provider-desktop/nadp-read.c
@@ -37,6 +37,7 @@
 #include "nadp-desktop-file.h"
 #include "nadp-desktop-provider.h"
 #include "nadp-read.h"
+#include "nadp-write.h"
 #include "nadp-utils.h"
 #include "nadp-xdg-data-dirs.h"
 
@@ -247,7 +248,6 @@ read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, N
 	gchar *tooltip;
 	gchar *icon;
 	gboolean enabled;
-	gchar *path;
 	gboolean writable;
 
 	id = nadp_desktop_file_get_id( ndf );
@@ -273,9 +273,7 @@ read_item_properties( const NadpDesktopProvider *provider, NAObjectItem *item, N
 	enabled = nadp_desktop_file_get_enabled( ndf );
 	na_object_set_enabled( item, enabled );
 
-	path = nadp_desktop_file_get_key_file_path( ndf );
-	writable = nadp_utils_is_writable_file( path );
-	g_free( path );
+	writable = nadp_iio_provider_is_writable( NA_IIO_PROVIDER( provider ), item );
 	na_object_set_readonly( item, !writable );
 
 	g_free( id );
diff --git a/nautilus-actions/io-provider-desktop/nadp-write.c b/nautilus-actions/io-provider-desktop/nadp-write.c
index 9a700fa..3099358 100644
--- a/nautilus-actions/io-provider-desktop/nadp-write.c
+++ b/nautilus-actions/io-provider-desktop/nadp-write.c
@@ -43,46 +43,60 @@
 static guint write_item( const NAIIOProvider *provider, const NAObjectItem *item, NadpDesktopFile *ndf, GSList **messages );
 
 /*
- * NadpDesktopProvider is willing to write if user data dir exists (or
- * can be created) and is writable
+ * API function: should only be called through NAIIOProvider interface
  */
 gboolean
 nadp_iio_provider_is_willing_to_write( const NAIIOProvider *provider )
 {
-	static const gchar *thisfn = "nadp_write_iio_provider_is_willing_to_write";
-	gboolean willing_to;
+	return( TRUE );
+}
+
+/*
+ * NadpDesktopProvider is able to write if user data dir exists (or
+ * can be created) and is writable
+ *
+ * API function: should only be called through NAIIOProvider interface
+ */
+gboolean
+nadp_iio_provider_is_able_to_write( const NAIIOProvider *provider )
+{
+	static const gchar *thisfn = "nadp_write_iio_provider_is_able_to_write";
+	gboolean able_to;
 	gchar *userdir;
 	GSList *messages;
 
-	willing_to = FALSE;
+	able_to = FALSE;
 	messages = NULL;
 
-	/*g_debug( "%s: provider=%p", thisfn, ( void * ) provider );*/
-	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), willing_to );
+	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), able_to );
 
 	userdir = nadp_xdg_data_dirs_get_user_dir( NADP_DESKTOP_PROVIDER( provider ), &messages );
 
 	if( g_file_test( userdir, G_FILE_TEST_IS_DIR )){
-		willing_to = nadp_utils_is_writable_dir( userdir );
+		able_to = nadp_utils_is_writable_dir( userdir );
 
 	} else if( g_mkdir_with_parents( userdir, 0700 )){
 		g_warning( "%s: %s: %s", thisfn, userdir, g_strerror( errno ));
 
 	} else {
-		willing_to = nadp_utils_is_writable_dir( userdir );
+		able_to = nadp_utils_is_writable_dir( userdir );
 	}
 
 	g_free( userdir );
 
-	return( willing_to );
+	return( able_to );
 }
 
 /*
- * the item has been initially readen from a desktop file
- * -> see if this initial desktop file is writable ?
+ * the item comes from being readen from a desktop file
+ * -> see if this desktop file is writable ?
+ *
+ * This is only used to setup the 'read-only' initial status of the
+ * NAObjectItem - We don't care of all events which can suddenly make
+ * this item becomes readonly (eventually we will deal for errors,
+ * and reset the flag at this time)
  *
- * else we are going to write a new desktop file in user data dir
- * -> see writability status of the desktop provider
+ * Internal function: do not call from outside the instance.
  */
 gboolean
 nadp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item )
@@ -108,9 +122,6 @@ nadp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem
 		path = nadp_desktop_file_get_key_file_path( ndf );
 		writable = nadp_utils_is_writable_file( path );
 		g_free( path );
-
-	} else {
-		writable = nadp_iio_provider_is_willing_to_write( provider );
 	}
 
 	return( writable );
@@ -130,7 +141,8 @@ nadp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem
 	gchar *fulldir;
 	gboolean dir_ok;
 
-	ret = NA_IIO_PROVIDER_NOT_WRITABLE;
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
+
 	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), ret );
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
 
@@ -189,13 +201,33 @@ nadp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem
 static guint
 write_item( const NAIIOProvider *provider, const NAObjectItem *item, NadpDesktopFile *ndf, GSList **messages )
 {
+	static const gchar *thisfn = "nadp_iio_provider_write_item";
 	guint ret;
+	NadpDesktopProvider *self;
 	gchar *label;
 	gchar *tooltip;
 	gchar *icon;
 	gboolean enabled;
 
-	ret = NA_IIO_PROVIDER_WRITE_OK;
+	g_debug( "%s: provider=%p (%s), item=%p (%s), messages=%p",
+			thisfn,
+			( void * ) provider, G_OBJECT_TYPE_NAME( provider ),
+			( void * ) item, G_OBJECT_TYPE_NAME( item ),
+			( void * ) messages );
+
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
+
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+
+	self = NADP_DESKTOP_PROVIDER( provider );
+
+	if( self->private->dispose_has_run ){
+		return( NA_IIO_PROVIDER_CODE_NOT_WILLING_TO_RUN );
+	}
+
+	ret = NA_IIO_PROVIDER_CODE_OK;
 
 	label = na_object_get_label( item );
 	nadp_desktop_file_set_label( ndf, label );
@@ -213,7 +245,7 @@ write_item( const NAIIOProvider *provider, const NAObjectItem *item, NadpDesktop
 	nadp_desktop_file_set_enabled( ndf, enabled );
 
 	if( !nadp_desktop_file_write( ndf )){
-		ret = NA_IIO_PROVIDER_WRITE_ERROR;
+		ret = NA_IIO_PROVIDER_CODE_WRITE_ERROR;
 	}
 
 	return( ret );
@@ -224,19 +256,26 @@ nadp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem
 {
 	static const gchar *thisfn = "nadp_iio_provider_delete_item";
 	guint ret;
+	NadpDesktopProvider *self;
 	NadpDesktopFile *ndf;
 	gchar *path;
 
-	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
-			thisfn, ( void * ) provider, ( void * ) item, G_OBJECT_TYPE_NAME( item ), messages );
+	g_debug( "%s: provider=%p (%s), item=%p (%s), messages=%p",
+			thisfn,
+			( void * ) provider, G_OBJECT_TYPE_NAME( provider ),
+			( void * ) item, G_OBJECT_TYPE_NAME( item ),
+			( void * ) messages );
+
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
-	ret = NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE;
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), ret );
 	g_return_val_if_fail( NADP_IS_DESKTOP_PROVIDER( provider ), ret );
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
 
-	if( na_object_is_readonly( item )){
-		g_warning( "%s: item=%p is read-only", thisfn, ( void * ) item );
-		return( NA_IIO_PROVIDER_NOT_WRITABLE );
+	self = NADP_DESKTOP_PROVIDER( provider );
+
+	if( self->private->dispose_has_run ){
+		return( NA_IIO_PROVIDER_CODE_NOT_WILLING_TO_RUN );
 	}
 
 	ndf = ( NadpDesktopFile * ) na_object_get_provider_data( item );
@@ -245,13 +284,13 @@ nadp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem
 		g_return_val_if_fail( NADP_IS_DESKTOP_FILE( ndf ), ret );
 		path = nadp_desktop_file_get_key_file_path( ndf );
 		if( nadp_utils_delete_file( path )){
-			ret = NA_IIO_PROVIDER_WRITE_OK;
+			ret = NA_IIO_PROVIDER_CODE_OK;
 		}
 		g_free( path );
 
 	} else {
 		g_warning( "%s: NadpDesktopFile is null", thisfn );
-		ret = NA_IIO_PROVIDER_WRITE_OK;
+		ret = NA_IIO_PROVIDER_CODE_OK;
 	}
 
 	return( ret );
diff --git a/nautilus-actions/io-provider-desktop/nadp-write.h b/nautilus-actions/io-provider-desktop/nadp-write.h
index 039e3aa..7be3b35 100644
--- a/nautilus-actions/io-provider-desktop/nadp-write.h
+++ b/nautilus-actions/io-provider-desktop/nadp-write.h
@@ -38,6 +38,8 @@ G_BEGIN_DECLS
 
 gboolean nadp_iio_provider_is_willing_to_write( const NAIIOProvider *provider );
 
+gboolean nadp_iio_provider_is_able_to_write( const NAIIOProvider *provider );
+
 gboolean nadp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item );
 
 guint    nadp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **messages );
diff --git a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
index 3584aa9..a0fac34 100644
--- a/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
+++ b/nautilus-actions/io-provider-gconf/nagp-gconf-provider.c
@@ -137,7 +137,7 @@ iio_provider_iface_init( NAIIOProviderInterface *iface )
 	iface->get_version = get_version;
 	iface->read_items = nagp_iio_provider_read_items;
 	iface->is_willing_to_write = nagp_iio_provider_is_willing_to_write;
-	iface->is_writable = nagp_iio_provider_is_writable;
+	iface->is_able_to_write = nagp_iio_provider_is_able_to_write;
 	iface->write_item = nagp_iio_provider_write_item;
 	iface->delete_item = nagp_iio_provider_delete_item;
 }
@@ -148,7 +148,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nagp_gconf_provider_instance_init";
 	NagpGConfProvider *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NAGP_IS_GCONF_PROVIDER( instance ));
 	self = NAGP_GCONF_PROVIDER( instance );
 
@@ -165,7 +166,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "nagp_gconf_provider_instance_dispose";
 	NagpGConfProvider *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NAGP_IS_GCONF_PROVIDER( object ));
 	self = NAGP_GCONF_PROVIDER( object );
 
diff --git a/nautilus-actions/io-provider-gconf/nagp-write.c b/nautilus-actions/io-provider-gconf/nagp-write.c
index 62c63b9..8cf8c67 100644
--- a/nautilus-actions/io-provider-gconf/nagp-write.c
+++ b/nautilus-actions/io-provider-gconf/nagp-write.c
@@ -49,21 +49,32 @@ static gboolean       write_list( NagpGConfProvider *gconf, const gchar *uuid, c
 static void           free_gslist( GSList *list );
 
 /*
- * Rationale: gconf reads its storage path in /etc/gconf/2/path ;
+ * API function: should only be called through NAIIOProvider interface
+ */
+gboolean
+nagp_iio_provider_is_willing_to_write( const NAIIOProvider *provider )
+{
+	return( TRUE );
+}
+
+/*
+ * Rationale: gconf reads its storage path from /etc/gconf/2/path ;
  * there is there a 'xml:readwrite:$(HOME)/.gconf' line, but I do not
  * known any way to get it programatically, so an admin may have set a
  * readwrite space elsewhere..
  *
- * So, I try to write a 'foo' key somewhere: if it is ok, then the
- * provider is supposed willing to write...
+ * So, we try to write a 'foo' key somewhere: if it is ok, then the
+ * provider is supposed able to write...
+ *
+ * API function: should only be called through NAIIOProvider interface
  */
 gboolean
-nagp_iio_provider_is_willing_to_write( const NAIIOProvider *provider )
+nagp_iio_provider_is_able_to_write( const NAIIOProvider *provider )
 {
-	/*static const gchar *thisfn = "nagp_iio_provider_is_willing_to_write";*/
+	/*static const gchar *thisfn = "nagp_iio_provider_is_able_to_write";*/
 	static const gchar *path = "/apps/nautilus-actions/foo";
 	NagpGConfProvider *self;
-	gboolean willing_to = FALSE;
+	gboolean able_to = FALSE;
 
 	/*g_debug( "%s: provider=%p", thisfn, ( void * ) provider );*/
 	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
@@ -74,55 +85,18 @@ nagp_iio_provider_is_willing_to_write( const NAIIOProvider *provider )
 	if( !self->private->dispose_has_run ){
 
 		if( !na_gconf_utils_write_string( self->private->gconf, path, "1", NULL )){
-			willing_to = FALSE;
+			able_to = FALSE;
 
 		} else if( !gconf_client_recursive_unset( self->private->gconf, path, 0, NULL )){
-			willing_to = FALSE;
+			able_to = FALSE;
 
 		} else {
-			willing_to = TRUE;
+			able_to = TRUE;
 		}
 	}
 
-	/*g_debug( "%s: provider=%p, willing_to=%s", thisfn, ( void * ) provider, willing_to ? "True":"False" );*/
-	return( willing_to );
-}
-
-/*
- * Though the provider writability has already been checked by the
- * program, we can only returns TRUE if the provider is willing to write.
- * We so have to re-check it here.
- *
- * If the provider is set, we are able to use the 'read-only' flag of
- * the object. Else, we returns the provider itself writability status.
- */
-gboolean
-nagp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item )
-{
-	static const gchar *thisfn = "nagp_write_iio_provider_is_writable";
-	NagpGConfProvider *self;
-	gboolean willing_to = FALSE;
-	NAIIOProvider *origin;
-
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), FALSE );
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
-	self = NAGP_GCONF_PROVIDER( provider );
-
-	if( !self->private->dispose_has_run ){
-
-		origin = na_object_get_provider( item );
-		if( origin ){
-			willing_to = !na_object_is_readonly( item );
-		} else {
-			willing_to = nagp_iio_provider_is_willing_to_write( provider );
-		}
-	}
-
-	g_debug( "%s: provider=%p, item=%p, writable=%s",
-			thisfn, ( void * ) provider, ( void * ) item, willing_to ? "True":"False" );
-
-	return( willing_to );
+	/*g_debug( "%s: provider=%p, able_to=%s", thisfn, ( void * ) provider, able_to ? "True":"False" );*/
+	return( able_to );
 }
 
 /*
@@ -133,35 +107,46 @@ nagp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem
 {
 	static const gchar *thisfn = "nagp_gconf_provider_iio_provider_write_item";
 	NagpGConfProvider *self;
+	guint ret;
 
-	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
-			thisfn, ( void * ) provider,
-			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_debug( "%s: provider=%p (%s), item=%p (%s), messages=%p",
+			thisfn,
+			( void * ) provider, G_OBJECT_TYPE_NAME( provider ),
+			( void * ) item, G_OBJECT_TYPE_NAME( item ),
+			( void * ) messages );
+
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
+
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
 
 	self = NAGP_GCONF_PROVIDER( provider );
 
 	if( self->private->dispose_has_run ){
-		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+		return( NA_IIO_PROVIDER_CODE_NOT_WILLING_TO_RUN );
 	}
 
-	if( NA_IS_OBJECT_ACTION( item )){
-		if( !write_item_action( self, NA_OBJECT_ACTION( item ), messages )){
-			return( NA_IIO_PROVIDER_WRITE_ERROR );
+	ret = nagp_iio_provider_delete_item( provider, item, messages );
+
+	if( ret == NA_IIO_PROVIDER_CODE_OK ){
+
+		if( NA_IS_OBJECT_ACTION( item )){
+			if( !write_item_action( self, NA_OBJECT_ACTION( item ), messages )){
+				return( NA_IIO_PROVIDER_CODE_WRITE_ERROR );
+			}
 		}
-	}
 
-	if( NA_IS_OBJECT_MENU( item )){
-		if( !write_item_menu( self, NA_OBJECT_MENU( item ), messages )){
-			return( NA_IIO_PROVIDER_WRITE_ERROR );
+		if( NA_IS_OBJECT_MENU( item )){
+			if( !write_item_menu( self, NA_OBJECT_MENU( item ), messages )){
+				return( NA_IIO_PROVIDER_CODE_WRITE_ERROR );
+			}
 		}
 	}
 
 	gconf_client_suggest_sync( self->private->gconf, NULL );
 
-	return( NA_IIO_PROVIDER_WRITE_OK );
+	return( ret );
 }
 
 static gboolean
@@ -261,21 +246,25 @@ nagp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem
 	gchar *uuid, *path;
 	GError *error = NULL;
 
-	g_debug( "%s: provider=%p, item=%p (%s), messages=%p",
-			thisfn, ( void * ) provider,
-			( void * ) item, G_OBJECT_TYPE_NAME( item ), ( void * ) messages );
+	g_debug( "%s: provider=%p (%s), item=%p (%s), messages=%p",
+			thisfn,
+			( void * ) provider, G_OBJECT_TYPE_NAME( provider ),
+			( void * ) item, G_OBJECT_TYPE_NAME( item ),
+			( void * ) messages );
 
-	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
+
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NAGP_IS_GCONF_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
 
 	self = NAGP_GCONF_PROVIDER( provider );
 
 	if( self->private->dispose_has_run ){
-		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+		return( NA_IIO_PROVIDER_CODE_NOT_WILLING_TO_RUN );
 	}
 
-	ret = NA_IIO_PROVIDER_WRITE_OK;
+	ret = NA_IIO_PROVIDER_CODE_OK;
 	uuid = na_object_get_id( NA_OBJECT( item ));
 
 	path = g_strdup_printf( "%s%s/%s", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NA_GCONF_CONFIG_PATH, uuid );
@@ -285,23 +274,25 @@ nagp_iio_provider_delete_item( const NAIIOProvider *provider, const NAObjectItem
 		*messages = g_slist_append( *messages, g_strdup( error->message ));
 		g_error_free( error );
 		error = NULL;
+		ret = NA_IIO_PROVIDER_CODE_DELETE_SCHEMAS_ERROR;
 	}
 	g_free( path );
 
+	if( ret == NA_IIO_PROVIDER_CODE_OK ){
+		path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
+		gconf_client_recursive_unset( self->private->gconf, path, 0, &error );
+		if( error ){
+			g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+			*messages = g_slist_append( *messages, g_strdup( error->message ));
+			g_error_free( error );
+			error = NULL;
+			ret = NA_IIO_PROVIDER_CODE_DELETE_CONFIG_ERROR;
+		}
+	}
 
-	path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
-	if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
-		g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
-		*messages = g_slist_append( *messages, g_strdup( error->message ));
-		g_error_free( error );
-		error = NULL;
-		ret = NA_IIO_PROVIDER_WRITE_ERROR;
+	gconf_client_suggest_sync( self->private->gconf, NULL );
 
-	} else {
-		gconf_client_suggest_sync( self->private->gconf, NULL );
-	}
 	g_free( path );
-
 	g_free( uuid );
 
 	return( ret );
diff --git a/nautilus-actions/io-provider-gconf/nagp-write.h b/nautilus-actions/io-provider-gconf/nagp-write.h
index 8f45335..bf01577 100644
--- a/nautilus-actions/io-provider-gconf/nagp-write.h
+++ b/nautilus-actions/io-provider-gconf/nagp-write.h
@@ -40,7 +40,7 @@ G_BEGIN_DECLS
 
 gboolean nagp_iio_provider_is_willing_to_write( const NAIIOProvider *provider );
 
-gboolean nagp_iio_provider_is_writable( const NAIIOProvider *provider, const NAObjectItem *item );
+gboolean nagp_iio_provider_is_able_to_write( const NAIIOProvider *provider );
 
 guint    nagp_iio_provider_write_item( const NAIIOProvider *provider, const NAObjectItem *item, GSList **message );
 
diff --git a/nautilus-actions/nact/base-application.c b/nautilus-actions/nact/base-application.c
index a6ecdb3..5bcf884 100644
--- a/nautilus-actions/nact/base-application.c
+++ b/nautilus-actions/nact/base-application.c
@@ -275,15 +275,16 @@ class_init( BaseApplicationClass *klass )
 }
 
 static void
-instance_init( GTypeInstance *instance, gpointer klass )
+instance_init( GTypeInstance *application, gpointer klass )
 {
 	static const gchar *thisfn = "base_application_instance_init";
 	BaseApplication *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: application=%p (%s), klass=%p",
+			thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ), ( void * ) klass );
 
-	g_return_if_fail( BASE_IS_APPLICATION( instance ));
-	self = BASE_APPLICATION( instance );
+	g_return_if_fail( BASE_IS_APPLICATION( application ));
+	self = BASE_APPLICATION( application );
 
 	self->private = g_new0( BaseApplicationPrivate, 1 );
 
@@ -415,7 +416,7 @@ instance_dispose( GObject *application )
 	static const gchar *thisfn = "base_application_instance_dispose";
 	BaseApplication *self;
 
-	g_debug( "%s: application=%p", thisfn, ( void * ) application );
+	g_debug( "%s: application=%p (%s)", thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ));
 	g_return_if_fail( BASE_IS_APPLICATION( application ));
 	self = BASE_APPLICATION( application );
 
diff --git a/nautilus-actions/nact/base-assistant.c b/nautilus-actions/nact/base-assistant.c
index 5326b3d..f932e4c 100644
--- a/nautilus-actions/nact/base-assistant.c
+++ b/nautilus-actions/nact/base-assistant.c
@@ -181,7 +181,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "base_assistant_instance_init";
 	BaseAssistant *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 
 	g_return_if_fail( BASE_IS_ASSISTANT( instance ));
 	self = BASE_ASSISTANT( instance );
@@ -274,7 +275,7 @@ instance_dispose( GObject *window )
 	static const gchar *thisfn = "base_assistant_instance_dispose";
 	BaseAssistant *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window  ));
 	g_return_if_fail( BASE_IS_ASSISTANT( window ));
 	self = BASE_ASSISTANT( window );
 
diff --git a/nautilus-actions/nact/base-builder.c b/nautilus-actions/nact/base-builder.c
index db186e5..e6eb398 100644
--- a/nautilus-actions/nact/base-builder.c
+++ b/nautilus-actions/nact/base-builder.c
@@ -119,7 +119,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "base_builder_instance_init";
 	BaseBuilder *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 
 	g_return_if_fail( BASE_IS_BUILDER( instance ));
 	self = BASE_BUILDER( instance );
@@ -130,14 +131,14 @@ instance_init( GTypeInstance *instance, gpointer klass )
 }
 
 static void
-instance_dispose( GObject *window )
+instance_dispose( GObject *instance )
 {
 	static const gchar *thisfn = "base_builder_instance_dispose";
 	BaseBuilder *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
-	g_return_if_fail( BASE_IS_BUILDER( window ));
-	self = BASE_BUILDER( window );
+	g_debug( "%s: instance=%p (%s)", thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
+	g_return_if_fail( BASE_IS_BUILDER( instance ));
+	self = BASE_BUILDER( instance );
 
 	if( !self->private->dispose_has_run ){
 
@@ -145,7 +146,7 @@ instance_dispose( GObject *window )
 
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
-			G_OBJECT_CLASS( st_parent_class )->dispose( window );
+			G_OBJECT_CLASS( st_parent_class )->dispose( instance );
 		}
 	}
 }
diff --git a/nautilus-actions/nact/base-dialog.c b/nautilus-actions/nact/base-dialog.c
index 9913e8c..66fff3c 100644
--- a/nautilus-actions/nact/base-dialog.c
+++ b/nautilus-actions/nact/base-dialog.c
@@ -114,7 +114,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "base_dialog_instance_init";
 	BaseDialog *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( BASE_IS_DIALOG( instance ));
 	self = BASE_DIALOG( instance );
 
@@ -129,7 +130,7 @@ instance_dispose( GObject *window )
 	static const gchar *thisfn = "base_dialog_instance_dispose";
 	BaseDialog *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
 	g_return_if_fail( BASE_IS_DIALOG( window ));
 	self = BASE_DIALOG( window );
 
diff --git a/nautilus-actions/nact/base-window.c b/nautilus-actions/nact/base-window.c
index ec39faa..631c59b 100644
--- a/nautilus-actions/nact/base-window.c
+++ b/nautilus-actions/nact/base-window.c
@@ -344,7 +344,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "base_window_instance_init";
 	BaseWindow *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( BASE_IS_WINDOW( instance ));
 	self = BASE_WINDOW( instance );
 
@@ -470,7 +471,7 @@ instance_dispose( GObject *window )
 	BaseWindow *self;
 	GSList *is;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
 	g_return_if_fail( BASE_IS_WINDOW( window ));
 	self = BASE_WINDOW( window );
 
diff --git a/nautilus-actions/nact/nact-application.c b/nautilus-actions/nact/nact-application.c
index 51d2726..ce86e00 100644
--- a/nautilus-actions/nact/nact-application.c
+++ b/nautilus-actions/nact/nact-application.c
@@ -171,14 +171,15 @@ class_init( NactApplicationClass *klass )
 }
 
 static void
-instance_init( GTypeInstance *instance, gpointer klass )
+instance_init( GTypeInstance *application, gpointer klass )
 {
 	static const gchar *thisfn = "nact_application_instance_init";
 	NactApplication *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
-	g_assert( NACT_IS_APPLICATION( instance ));
-	self = NACT_APPLICATION( instance );
+	g_debug( "%s: application=%p (%s), klass=%p",
+			thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ), ( void * ) klass );
+	g_assert( NACT_IS_APPLICATION( application ));
+	self = NACT_APPLICATION( application );
 
 	self->private = g_new0( NactApplicationPrivate, 1 );
 
@@ -235,7 +236,7 @@ instance_dispose( GObject *application )
 	static const gchar *thisfn = "nact_application_instance_dispose";
 	NactApplication *self;
 
-	g_debug( "%s: application=%p", thisfn, ( void * ) application );
+	g_debug( "%s: application=%p (%s)", thisfn, ( void * ) application, G_OBJECT_TYPE_NAME( application ));
 	g_return_if_fail( NACT_IS_APPLICATION( application ));
 	self = NACT_APPLICATION( application );
 
@@ -394,7 +395,7 @@ appli_initialize_application( BaseApplication *application )
 	fake = na_object_action_new();
 	g_object_unref( fake );
 
-	NACT_APPLICATION( application )->private->pivot = na_pivot_new( PIVOT_LOAD_ALL, PIVOT_IO_PROVIDER_ALL );
+	NACT_APPLICATION( application )->private->pivot = na_pivot_new( PIVOT_LOAD_ALL );
 	na_pivot_load_items( NACT_APPLICATION( application )->private->pivot );
 
 	/* call parent class */
diff --git a/nautilus-actions/nact/nact-assistant-export-ask.c b/nautilus-actions/nact/nact-assistant-export-ask.c
index 7bbf0c0..a360076 100644
--- a/nautilus-actions/nact/nact-assistant-export-ask.c
+++ b/nautilus-actions/nact/nact-assistant-export-ask.c
@@ -145,7 +145,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_assistant_export_ask_instance_init";
 	NactAssistantExportAsk *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT_ASK( instance ));
 	self = NACT_ASSISTANT_EXPORT_ASK( instance );
 
@@ -178,7 +179,7 @@ instance_dispose( GObject *dialog )
 	static const gchar *thisfn = "nact_assistant_export_ask_instance_dispose";
 	NactAssistantExportAsk *self;
 
-	g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+	g_debug( "%s: dialog=%p (%s)", thisfn, ( void * ) dialog, G_OBJECT_TYPE_NAME( dialog ));
 	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT_ASK( dialog ));
 	self = NACT_ASSISTANT_EXPORT_ASK( dialog );
 
diff --git a/nautilus-actions/nact/nact-assistant-export.c b/nautilus-actions/nact/nact-assistant-export.c
index 7289a61..dc2630c 100644
--- a/nautilus-actions/nact/nact-assistant-export.c
+++ b/nautilus-actions/nact/nact-assistant-export.c
@@ -239,7 +239,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_assistant_export_instance_init";
 	NactAssistantExport *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_assert( NACT_IS_ASSISTANT_EXPORT( instance ));
 	self = NACT_ASSISTANT_EXPORT( instance );
 
@@ -266,7 +267,7 @@ instance_dispose( GObject *window )
 	static const gchar *thisfn = "nact_assistant_export_instance_dispose";
 	NactAssistantExport *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
 	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT( window ));
 	self = NACT_ASSISTANT_EXPORT( window );
 
diff --git a/nautilus-actions/nact/nact-assistant-import-ask.c b/nautilus-actions/nact/nact-assistant-import-ask.c
index 668502b..c734954 100644
--- a/nautilus-actions/nact/nact-assistant-import-ask.c
+++ b/nautilus-actions/nact/nact-assistant-import-ask.c
@@ -145,7 +145,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_assistant_import_ask_instance_init";
 	NactAssistantImportAsk *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_ASSISTANT_IMPORT_ASK( instance ));
 	self = NACT_ASSISTANT_IMPORT_ASK( instance );
 
@@ -178,7 +179,7 @@ instance_dispose( GObject *dialog )
 	static const gchar *thisfn = "nact_assistant_import_ask_instance_dispose";
 	NactAssistantImportAsk *self;
 
-	g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+	g_debug( "%s: dialog=%p (%s)", thisfn, ( void * ) dialog, G_OBJECT_TYPE_NAME( dialog ));
 	g_return_if_fail( NACT_IS_ASSISTANT_IMPORT_ASK( dialog ));
 	self = NACT_ASSISTANT_IMPORT_ASK( dialog );
 
diff --git a/nautilus-actions/nact/nact-assistant-import.c b/nautilus-actions/nact/nact-assistant-import.c
index 6ca6388..99e8dac 100644
--- a/nautilus-actions/nact/nact-assistant-import.c
+++ b/nautilus-actions/nact/nact-assistant-import.c
@@ -192,7 +192,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_assistant_import_instance_init";
 	NactAssistantImport *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_ASSISTANT_IMPORT( instance ));
 	self = NACT_ASSISTANT_IMPORT( instance );
 
@@ -220,7 +221,7 @@ instance_dispose( GObject *window )
 	static const gchar *thisfn = "nact_assistant_import_instance_dispose";
 	NactAssistantImport *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
 	g_return_if_fail( NACT_IS_ASSISTANT_IMPORT( window ));
 	self = NACT_ASSISTANT_IMPORT( window );
 
diff --git a/nautilus-actions/nact/nact-clipboard.c b/nautilus-actions/nact/nact-clipboard.c
index f5eeaae..0f4cc51 100644
--- a/nautilus-actions/nact/nact-clipboard.c
+++ b/nautilus-actions/nact/nact-clipboard.c
@@ -187,7 +187,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	NactClipboard *self;
 	GdkDisplay *display;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_assert( NACT_IS_CLIPBOARD( instance ));
 	self = NACT_CLIPBOARD( instance );
 
@@ -202,14 +203,14 @@ instance_init( GTypeInstance *instance, gpointer klass )
 }
 
 static void
-instance_dispose( GObject *window )
+instance_dispose( GObject *object )
 {
 	static const gchar *thisfn = "nact_clipboard_instance_dispose";
 	NactClipboard *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
-	g_assert( NACT_IS_CLIPBOARD( window ));
-	self = NACT_CLIPBOARD( window );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+	g_assert( NACT_IS_CLIPBOARD( object ));
+	self = NACT_CLIPBOARD( object );
 
 	if( !self->private->dispose_has_run ){
 
@@ -220,7 +221,7 @@ instance_dispose( GObject *window )
 
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
-			G_OBJECT_CLASS( st_parent_class )->dispose( window );
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
 		}
 	}
 }
diff --git a/nautilus-actions/nact/nact-confirm-logout.c b/nautilus-actions/nact/nact-confirm-logout.c
index 505a1c9..919725b 100644
--- a/nautilus-actions/nact/nact-confirm-logout.c
+++ b/nautilus-actions/nact/nact-confirm-logout.c
@@ -140,7 +140,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_confirm_logout_instance_init";
 	NactConfirmLogout *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_CONFIRM_LOGOUT( instance ));
 	self = NACT_CONFIRM_LOGOUT( instance );
 
@@ -173,7 +174,7 @@ instance_dispose( GObject *dialog )
 	static const gchar *thisfn = "nact_confirm_logout_instance_dispose";
 	NactConfirmLogout *self;
 
-	g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+	g_debug( "%s: dialog=%p (%s)", thisfn, ( void * ) dialog, G_OBJECT_TYPE_NAME( dialog ));
 	g_return_if_fail( NACT_IS_CONFIRM_LOGOUT( dialog ));
 	self = NACT_CONFIRM_LOGOUT( dialog );
 
diff --git a/nautilus-actions/nact/nact-iaction-tab.c b/nautilus-actions/nact/nact-iaction-tab.c
index cad531a..057454a 100644
--- a/nautilus-actions/nact/nact-iaction-tab.c
+++ b/nautilus-actions/nact/nact-iaction-tab.c
@@ -416,8 +416,7 @@ on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selecte
 	GtkToggleButton *readonly_button;
 	gboolean enabled_item;
 	GtkToggleButton *toggle;
-	gboolean readonly;
-	gboolean readonly_item, writable_provider;
+	gboolean editable;
 
 	g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
 	g_return_if_fail( BASE_IS_WINDOW( instance ));
@@ -432,8 +431,7 @@ on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selecte
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		g_return_if_fail( !item || NA_IS_OBJECT_ITEM( item ));
@@ -452,17 +450,15 @@ on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selecte
 		target_toolbar = ( item && (
 				( NA_IS_OBJECT_ACTION( item ) && na_object_action_is_target_toolbar( NA_OBJECT_ACTION( item )))));
 
-		readonly = readonly_item || !writable_provider;
-
 		toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetSelectionButton" ));
 		gtk_toggle_button_set_active( toggle, target_selection );
 		gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
-		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
 
 		toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetBackgroundButton" ));
 		gtk_toggle_button_set_active( toggle, target_background );
 		gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
-		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
 
 		enable_label = ( item && ( NA_IS_OBJECT_MENU( item ) || target_selection || target_background ));
 		label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionMenuLabelEntry" );
@@ -473,43 +469,43 @@ on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selecte
 		}
 		g_free( label );
 		gtk_widget_set_sensitive( label_widget, enable_label );
-		nact_gtk_utils_set_editable( GTK_OBJECT( label_widget ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( label_widget ), editable );
 
 		toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionTargetToolbarButton" ));
 		gtk_toggle_button_set_active( toggle, target_toolbar );
 		gtk_widget_set_sensitive( GTK_WIDGET( toggle ), item && NA_IS_OBJECT_ACTION( item ));
-		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
 
 		toggle = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ToolbarSameLabelButton" ));
 		same_label = item && NA_IS_OBJECT_ACTION( item ) ? na_object_action_toolbar_use_same_label( NA_OBJECT_ACTION( item )) : FALSE;
 		gtk_toggle_button_set_active( toggle, same_label );
 		toolbar_same_label_set_sensitive( instance, item );
-		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( toggle ), editable );
 
 		label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconLabelEntry" );
 		label = item && NA_IS_OBJECT_ACTION( item ) ? na_object_action_toolbar_get_label( NA_OBJECT_ACTION( item )) : g_strdup( "" );
 		gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
 		g_free( label );
 		toolbar_label_set_sensitive( instance, item );
-		nact_gtk_utils_set_editable( GTK_OBJECT( label_widget ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( label_widget ), editable );
 
 		tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
 		tooltip = item ? na_object_get_tooltip( item ) : g_strdup( "" );
 		gtk_entry_set_text( GTK_ENTRY( tooltip_widget ), tooltip );
 		g_free( tooltip );
 		gtk_widget_set_sensitive( tooltip_widget, item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( tooltip_widget ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( tooltip_widget ), editable );
 
 		icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
 		icon = item ? na_object_get_icon( item ) : g_strdup( "" );
 		gtk_entry_set_text( GTK_ENTRY( GTK_BIN( icon_widget )->child ), icon );
 		g_free( icon );
 		gtk_widget_set_sensitive( icon_widget, item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( icon_widget ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( icon_widget ), editable );
 
 		icon_button = GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" ));
 		gtk_widget_set_sensitive( GTK_WIDGET( icon_button ), item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( icon_button ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( icon_button ), editable );
 
 		title_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionPropertiesTitle" );
 		if( item && NA_IS_OBJECT_MENU( item )){
@@ -522,13 +518,13 @@ on_tab_updatable_selection_changed( NactIActionTab *instance, gint count_selecte
 		enabled_item = item ? na_object_is_enabled( NA_OBJECT_ITEM( item )) : FALSE;
 		gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( enabled_button ), enabled_item );
 		gtk_widget_set_sensitive( GTK_WIDGET( enabled_button ), item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( enabled_button ), !readonly );
+		nact_gtk_utils_set_editable( GTK_OBJECT( enabled_button ), editable );
 
 		/* read-only toggle only indicates the writability status of this item
 		 * _not_ the writability status of the provider
 		 */
 		readonly_button = GTK_TOGGLE_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionReadonlyButton" ));
-		gtk_toggle_button_set_active( readonly_button, readonly_item );
+		gtk_toggle_button_set_active( readonly_button, item ? na_object_is_readonly( item ) : FALSE );
 		gtk_widget_set_sensitive( GTK_WIDGET( readonly_button ), item != NULL );
 		nact_gtk_utils_set_editable( GTK_OBJECT( readonly_button ), FALSE );
 
@@ -567,8 +563,7 @@ on_target_selection_toggled( GtkToggleButton *button, NactIActionTab *instance )
 	static const gchar *thisfn = "nact_iaction_tab_on_target_selection_toggled";
 	NAObjectAction *action;
 	gboolean is_target;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 		g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
@@ -576,27 +571,26 @@ on_target_selection_toggled( GtkToggleButton *button, NactIActionTab *instance )
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &action,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
-		g_debug( "%s: item=%p (%s), readonly_item=%s, writable_provider=%s",
+		g_debug( "%s: item=%p (%s), editable=%s",
 				thisfn, ( void * ) action, action ? G_OBJECT_TYPE_NAME( action ) : "(null)",
-				readonly_item ? "True":"False", writable_provider ? "True":"False" );
+				editable ? "True":"False" );
 
 		if( action && NA_IS_OBJECT_ACTION( action )){
 
 			is_target = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
-				g_signal_handlers_block_by_func(( gpointer ) button, on_target_selection_toggled, instance );
-				gtk_toggle_button_set_active( button, !is_target );
-				g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_selection_toggled, instance );
-
-			} else {
+			if( editable ){
 				na_object_action_set_target_selection( action, is_target );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ENABLE_TAB, action );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, action, FALSE );
+
+			} else {
+				g_signal_handlers_block_by_func(( gpointer ) button, on_target_selection_toggled, instance );
+				gtk_toggle_button_set_active( button, !is_target );
+				g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_selection_toggled, instance );
 			}
 		}
 	}
@@ -608,8 +602,7 @@ on_target_background_toggled( GtkToggleButton *button, NactIActionTab *instance
 	static const gchar *thisfn = "nact_iaction_tab_on_target_background_toggled";
 	NAObjectAction *action;
 	gboolean is_target;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 		g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
@@ -617,23 +610,22 @@ on_target_background_toggled( GtkToggleButton *button, NactIActionTab *instance
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &action,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		if( action && NA_IS_OBJECT_ACTION( action )){
 
 			is_target = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
-				g_signal_handlers_block_by_func(( gpointer ) button, on_target_background_toggled, instance );
-				gtk_toggle_button_set_active( button, !is_target );
-				g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_background_toggled, instance );
-
-			} else {
+			if( editable ){
 				na_object_action_set_target_background( action, is_target );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ENABLE_TAB, action );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, action, FALSE );
+
+			} else {
+				g_signal_handlers_block_by_func(( gpointer ) button, on_target_background_toggled, instance );
+				gtk_toggle_button_set_active( button, !is_target );
+				g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_background_toggled, instance );
 			}
 		}
 	}
@@ -722,8 +714,7 @@ on_target_toolbar_toggled( GtkToggleButton *button, NactIActionTab *instance )
 	static const gchar *thisfn = "nact_iaction_tab_on_target_toolbar_toggled";
 	NAObjectAction *action;
 	gboolean is_target;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 		g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
@@ -731,25 +722,24 @@ on_target_toolbar_toggled( GtkToggleButton *button, NactIActionTab *instance )
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &action,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		if( action && NA_IS_OBJECT_ACTION( action )){
 
 			is_target = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
-				g_signal_handlers_block_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
-				gtk_toggle_button_set_active( button, !is_target );
-				g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
-
-			} else {
+			if( editable ){
 				na_object_action_set_target_toolbar( action, is_target );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ENABLE_TAB, action );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, action, FALSE );
 				toolbar_same_label_set_sensitive( instance, NA_OBJECT_ITEM( action ));
 				toolbar_label_set_sensitive( instance, NA_OBJECT_ITEM( action ));
+
+			} else {
+				g_signal_handlers_block_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
+				gtk_toggle_button_set_active( button, !is_target );
+				g_signal_handlers_unblock_by_func(( gpointer ) button, on_target_toolbar_toggled, instance );
 			}
 		}
 	}
@@ -761,8 +751,7 @@ on_toolbar_same_label_toggled( GtkToggleButton *button, NactIActionTab *instance
 	static const gchar *thisfn = "nact_iaction_tab_on_toolbar_same_label_toggled";
 	NAObjectItem *edited;
 	gboolean same_label;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 		g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
@@ -770,24 +759,23 @@ on_toolbar_same_label_toggled( GtkToggleButton *button, NactIActionTab *instance
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		if( edited && NA_IS_OBJECT_ACTION( edited )){
 
 			same_label = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
-				g_signal_handlers_block_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
-				gtk_toggle_button_set_active( button, !same_label );
-				g_signal_handlers_unblock_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
-
-			} else {
+			if( editable ){
 				na_object_action_toolbar_set_same_label( NA_OBJECT_ACTION( edited ), same_label );
 				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
 				toolbar_same_label_set_sensitive( instance, NA_OBJECT_ITEM( edited ));
 				toolbar_label_set_sensitive( instance, NA_OBJECT_ITEM( edited ));
+
+			} else {
+				g_signal_handlers_block_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
+				gtk_toggle_button_set_active( button, !same_label );
+				g_signal_handlers_unblock_by_func(( gpointer ) button, on_toolbar_same_label_toggled, instance );
 			}
 		}
 	}
@@ -1060,8 +1048,7 @@ on_enabled_toggled( GtkToggleButton *button, NactIActionTab *instance )
 	static const gchar *thisfn = "nact_iaction_tab_on_enabled_toggled";
 	NAObjectItem *edited;
 	gboolean enabled;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 		g_debug( "%s: button=%p, instance=%p", thisfn, ( void * ) button, ( void * ) instance );
@@ -1069,22 +1056,21 @@ on_enabled_toggled( GtkToggleButton *button, NactIActionTab *instance )
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		if( edited && NA_IS_OBJECT_ITEM( edited )){
 
 			enabled = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
+			if( editable ){
+				na_object_item_set_enabled( edited, enabled );
+				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
+
+			} else {
 				g_signal_handlers_block_by_func(( gpointer ) button, on_enabled_toggled, instance );
 				gtk_toggle_button_set_active( button, !enabled );
 				g_signal_handlers_unblock_by_func(( gpointer ) button, on_enabled_toggled, instance );
-
-			} else {
-				na_object_item_set_enabled( edited, enabled );
-				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
 			}
 		}
 	}
@@ -1112,14 +1098,14 @@ display_provider_name( NactIActionTab *instance, NAPivot *pivot, NAObjectItem *i
 {
 	GtkWidget *label_widget;
 	gchar *label;
-	NAIIOProvider *provider;
+	NAIOProvider *provider;
 
 	label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionItemProvider" );
 	label = NULL;
 	if( item ){
 		provider = na_object_get_provider( item );
 		if( provider ){
-			label = na_io_provider_get_provider_name( provider );
+			label = na_io_provider_get_name( provider );
 		}
 	}
 	if( !label ){
diff --git a/nautilus-actions/nact/nact-iactions-list-bis.c b/nautilus-actions/nact/nact-iactions-list-bis.c
index 36f1fed..f8880cc 100644
--- a/nautilus-actions/nact/nact-iactions-list-bis.c
+++ b/nautilus-actions/nact/nact-iactions-list-bis.c
@@ -567,6 +567,13 @@ nact_iactions_list_bis_list_modified_items( NactIActionsList *instance )
 	if( st_iactions_list_initialized && !st_iactions_list_finalized ){
 
 		ialid = nact_iactions_list_priv_get_instance_data( instance );
+
+		g_debug( "%s: raw list", thisfn );
+		for( it = ialid->modified_items ; it ; it = it->next ){
+			g_debug( "%s: %p (%s)", thisfn, ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ));
+		}
+
+		g_debug( "%s: detailed list", thisfn );
 		for( it = ialid->modified_items ; it ; it = it->next ){
 			na_object_dump( it->data );
 		}
@@ -577,10 +584,10 @@ nact_iactions_list_bis_list_modified_items( NactIActionsList *instance )
  * nact_iactions_list_bis_removed_modified:
  * @instance: this #NactIActionsList instance.
  *
- * Clears the modified items list.
+ * Removes the saved item from the modified items list.
  */
 void
-nact_iactions_list_bis_removed_modified( NactIActionsList *instance )
+nact_iactions_list_bis_removed_modified( NactIActionsList *instance, const NAObjectItem *item )
 {
 	IActionsListInstanceData *ialid;
 
@@ -589,8 +596,11 @@ nact_iactions_list_bis_removed_modified( NactIActionsList *instance )
 	if( st_iactions_list_initialized && !st_iactions_list_finalized ){
 
 		ialid = nact_iactions_list_priv_get_instance_data( instance );
-		g_list_free( ialid->modified_items );
-		ialid->modified_items = NULL;
+		ialid->modified_items = g_list_remove( ialid->modified_items, item );
+		if( g_list_length( ialid->modified_items ) == 0 ){
+			g_list_free( ialid->modified_items );
+			ialid->modified_items = NULL;
+		}
 	}
 }
 
diff --git a/nautilus-actions/nact/nact-iactions-list.c b/nautilus-actions/nact/nact-iactions-list.c
index 9cdf049..5259fd2 100644
--- a/nautilus-actions/nact/nact-iactions-list.c
+++ b/nautilus-actions/nact/nact-iactions-list.c
@@ -853,8 +853,8 @@ display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *m
 	gboolean valid = TRUE;
 	IActionsListInstanceData *ialid;
 	NAObjectItem *item;
-	gboolean writable_provider;
-	gboolean readonly_item;
+	NAPivot *pivot;
+	gboolean writable_item;
 
 	gtk_tree_model_get( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
 	g_object_unref( object );
@@ -870,8 +870,8 @@ display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *m
 		modified = na_object_is_modified( object );
 		valid = na_object_is_valid( object );
 		item = NA_IS_OBJECT_PROFILE( object ) ? na_object_get_parent( object ) : NA_OBJECT_ITEM( object );
-		readonly_item = na_object_is_readonly( item );
-		writable_provider = nact_window_is_writable_provider( NACT_WINDOW( instance ), item );
+		pivot = nact_window_get_pivot( NACT_WINDOW( instance ));
+		writable_item = na_pivot_is_item_writable( pivot, item, NULL );
 
 		if( modified ){
 			g_object_set( cell, "style", PANGO_STYLE_ITALIC, "style-set", TRUE, NULL );
@@ -881,7 +881,7 @@ display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *m
 			g_object_set( cell, "foreground", "Red", "foreground-set", TRUE, NULL );
 		}
 
-		g_object_set( cell, "editable", writable_provider && !readonly_item, NULL );
+		g_object_set( cell, "editable", writable_item, NULL );
 	}
 
 	g_object_set( cell, "text", label, NULL );
diff --git a/nautilus-actions/nact/nact-iactions-list.h b/nautilus-actions/nact/nact-iactions-list.h
index 04e052b..caa179d 100644
--- a/nautilus-actions/nact/nact-iactions-list.h
+++ b/nautilus-actions/nact/nact-iactions-list.h
@@ -52,7 +52,7 @@
 
 #include <gtk/gtk.h>
 
-#include <private/na-object-class.h>
+#include <private/na-object-item-class.h>
 
 G_BEGIN_DECLS
 
@@ -148,7 +148,7 @@ void      nact_iactions_list_bis_insert_at_path( NactIActionsList *instance, GLi
 void      nact_iactions_list_bis_insert_items( NactIActionsList *instance, GList *items, NAObject *sibling );
 void      nact_iactions_list_bis_insert_into( NactIActionsList *instance, GList *items );
 void      nact_iactions_list_bis_list_modified_items( NactIActionsList *instance );
-void      nact_iactions_list_bis_removed_modified( NactIActionsList *instance );
+void      nact_iactions_list_bis_removed_modified( NactIActionsList *instance, const NAObjectItem *item );
 void      nact_iactions_list_bis_select_first_row( NactIActionsList *instance );
 void      nact_iactions_list_bis_select_row_at_path( NactIActionsList *instance, GtkTreeView *treeview, GtkTreeModel *model, GtkTreePath *path );
 void      nact_iactions_list_bis_toggle_collapse( NactIActionsList *instance );
diff --git a/nautilus-actions/nact/nact-iadvanced-tab.c b/nautilus-actions/nact/nact-iadvanced-tab.c
index b40f13f..70f4ba8 100644
--- a/nautilus-actions/nact/nact-iadvanced-tab.c
+++ b/nautilus-actions/nact/nact-iadvanced-tab.c
@@ -284,8 +284,7 @@ on_tab_updatable_selection_changed( NactIAdvancedTab *instance, gint count_selec
 	NAObjectProfile *profile;
 	gboolean enable_tab;
 	GSList *schemes;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	schemes = NULL;
 	if( st_initialized && !st_finalized ){
@@ -297,8 +296,7 @@ on_tab_updatable_selection_changed( NactIAdvancedTab *instance, gint count_selec
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
 				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		enable_tab = tab_set_sensitive( instance );
@@ -312,7 +310,7 @@ on_tab_updatable_selection_changed( NactIAdvancedTab *instance, gint count_selec
 				BASE_WINDOW( instance ),
 				schemes,
 				item && NA_IS_OBJECT_ACTION( item ),
-				writable_provider && !readonly_item );
+				editable );
 	}
 }
 
diff --git a/nautilus-actions/nact/nact-ibackground-tab.c b/nautilus-actions/nact/nact-ibackground-tab.c
index 44b10a0..99e6fe2 100644
--- a/nautilus-actions/nact/nact-ibackground-tab.c
+++ b/nautilus-actions/nact/nact-ibackground-tab.c
@@ -293,8 +293,7 @@ on_tab_updatable_selection_changed( NactIBackgroundTab *instance, gint count_sel
 	NAObjectItem *item;
 	NAObjectProfile *profile;
 	gboolean enable_tab;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 	GtkTreeView *treeview;
 	GtkTreeViewColumn *column;
 	GtkWidget *widget;
@@ -312,8 +311,7 @@ on_tab_updatable_selection_changed( NactIBackgroundTab *instance, gint count_sel
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
 				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		g_return_if_fail( !item || NA_IS_OBJECT_ITEM( item ));
@@ -327,15 +325,15 @@ on_tab_updatable_selection_changed( NactIBackgroundTab *instance, gint count_sel
 		treeview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( instance ), "FoldersTreeView" ));
 		gtk_widget_set_sensitive( GTK_WIDGET( treeview ), profile != NULL );
 		column = gtk_tree_view_get_column( treeview, BACKGROUND_URI_COLUMN );
-		nact_gtk_utils_set_editable( GTK_OBJECT( column ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( column ), editable );
 
 		widget = base_window_get_widget( BASE_WINDOW( instance ), "AddFolderButton" );
 		gtk_widget_set_sensitive( widget, profile != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( widget ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( widget ), editable );
 
 		widget = base_window_get_widget( BASE_WINDOW( instance ), "RemoveFolderButton" );
 		gtk_widget_set_sensitive( widget, profile != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( widget ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( widget ), editable );
 
 		st_on_selection_change = FALSE;
 	}
@@ -380,18 +378,16 @@ static gboolean
 on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIBackgroundTab *instance )
 {
 	gboolean stop;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	stop = FALSE;
 
 	g_object_get(
 			G_OBJECT( instance ),
-			TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-			TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+			TAB_UPDATABLE_PROP_EDITABLE, &editable,
 			NULL );
 
-	if( writable_provider && !readonly_item ){
+	if( editable ){
 
 		if( event->keyval == GDK_F2 ){
 			inline_edition( instance );
@@ -606,17 +602,15 @@ on_folder_uri_edited( GtkCellRendererText *renderer, const gchar *path, const gc
 static void
 on_folders_selection_changed( GtkTreeSelection *selection, NactIBackgroundTab *instance )
 {
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 	GtkWidget *button;
 
 	g_object_get(
 			G_OBJECT( instance ),
-			TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-			TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+			TAB_UPDATABLE_PROP_EDITABLE, &editable,
 			NULL );
 
-	if( writable_provider && !readonly_item ){
+	if( editable ){
 
 		button = base_window_get_widget( BASE_WINDOW( instance ), "RemoveFolderButton");
 		gtk_widget_set_sensitive( button, gtk_tree_selection_count_selected_rows( selection ) > 0 );
diff --git a/nautilus-actions/nact/nact-icommand-tab.c b/nautilus-actions/nact/nact-icommand-tab.c
index 748b099..b6f1fa6 100644
--- a/nautilus-actions/nact/nact-icommand-tab.c
+++ b/nautilus-actions/nact/nact-icommand-tab.c
@@ -321,8 +321,7 @@ on_tab_updatable_selection_changed( NactICommandTab *instance, gint count_select
 	gboolean enable_tab;
 	GtkWidget *label_entry, *path_entry, *parameters_entry;
 	gchar *label, *path, *parameters;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 	GtkButton *path_button;
 	GtkButton *legend_button;
 
@@ -337,8 +336,7 @@ on_tab_updatable_selection_changed( NactICommandTab *instance, gint count_select
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
 				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		enable_tab = tab_set_sensitive( instance );
@@ -349,25 +347,25 @@ on_tab_updatable_selection_changed( NactICommandTab *instance, gint count_select
 		check_for_label( instance, GTK_ENTRY( label_entry ), label );
 		g_free( label );
 		gtk_widget_set_sensitive( label_entry, profile != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( label_entry ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( label_entry ), editable );
 
 		path_entry = get_path_entry( instance );
 		path = profile ? na_object_profile_get_path( profile ) : g_strdup( "" );
 		gtk_entry_set_text( GTK_ENTRY( path_entry ), path );
 		g_free( path );
 		gtk_widget_set_sensitive( path_entry, profile != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( path_entry ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( path_entry ), editable );
 
 		path_button = get_path_button( instance );
 		gtk_widget_set_sensitive( GTK_WIDGET( path_button ), profile != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( path_button ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( path_button ), editable );
 
 		parameters_entry = get_parameters_entry( instance );
 		parameters = profile ? na_object_profile_get_parameters( profile ) : g_strdup( "" );
 		gtk_entry_set_text( GTK_ENTRY( parameters_entry ), parameters );
 		g_free( parameters );
 		gtk_widget_set_sensitive( parameters_entry, profile != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( parameters_entry ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( parameters_entry ), editable );
 
 		legend_button = get_legend_button( instance );
 		gtk_widget_set_sensitive( GTK_WIDGET( legend_button ), profile != NULL );
diff --git a/nautilus-actions/nact/nact-iconditions-tab.c b/nautilus-actions/nact/nact-iconditions-tab.c
index 6e650f1..73cb30c 100644
--- a/nautilus-actions/nact/nact-iconditions-tab.c
+++ b/nautilus-actions/nact/nact-iconditions-tab.c
@@ -311,8 +311,7 @@ on_tab_updatable_selection_changed( NactIConditionsTab *instance, gint count_sel
 	gboolean isfile, isdir;
 	GtkButton *multiple_button;
 	gboolean multiple;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
 	g_return_if_fail( NACT_IS_ICONDITIONS_TAB( instance ));
@@ -325,8 +324,7 @@ on_tab_updatable_selection_changed( NactIConditionsTab *instance, gint count_sel
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
 				TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		enable_tab = tab_set_sensitive( instance );
@@ -338,13 +336,13 @@ on_tab_updatable_selection_changed( NactIConditionsTab *instance, gint count_sel
 		g_free( basenames_text );
 		na_utils_free_string_list( basenames );
 		gtk_widget_set_sensitive( basenames_widget, item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( basenames_widget ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( basenames_widget ), editable );
 
 		matchcase_button = get_matchcase_button( instance );
 		matchcase = profile ? na_object_profile_get_matchcase( profile ) : FALSE;
 		gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( matchcase_button ), matchcase );
 		gtk_widget_set_sensitive( GTK_WIDGET( matchcase_button ), item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( matchcase_button ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( matchcase_button ), editable );
 
 		mimetypes_widget = get_mimetypes_entry( instance );
 		mimetypes = profile ? na_object_profile_get_mimetypes( profile ) : NULL;
@@ -353,17 +351,17 @@ on_tab_updatable_selection_changed( NactIConditionsTab *instance, gint count_sel
 		g_free( mimetypes_text );
 		na_utils_free_string_list( mimetypes );
 		gtk_widget_set_sensitive( mimetypes_widget, item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( mimetypes_widget ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( mimetypes_widget ), editable );
 
 		isfile = profile ? na_object_profile_get_is_file( profile ) : FALSE;
 		isdir = profile ? na_object_profile_get_is_dir( profile ) : FALSE;
-		set_isfiledir( instance, isfile, isdir, writable_provider && !readonly_item );
+		set_isfiledir( instance, isfile, isdir, editable );
 
 		multiple_button = get_multiple_button( instance );
 		multiple = profile ? na_object_profile_get_multiple( profile ) : FALSE;
 		gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( multiple_button ), multiple );
 		gtk_widget_set_sensitive( GTK_WIDGET( multiple_button ), item != NULL );
-		nact_gtk_utils_set_editable( GTK_OBJECT( multiple_button ), writable_provider && !readonly_item );
+		nact_gtk_utils_set_editable( GTK_OBJECT( multiple_button ), editable );
 
 		st_on_selection_change = FALSE;
 	}
@@ -478,8 +476,7 @@ on_isfiledir_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
 	/*static const gchar *thisfn = "nact_iconditions_tab_on_isfiledir_toggled";*/
 	NAObjectProfile *edited;
 	gboolean isfile, isdir;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 
@@ -488,23 +485,22 @@ on_isfiledir_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
 			g_object_get(
 					G_OBJECT( instance ),
 					TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
-					TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-					TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+					TAB_UPDATABLE_PROP_EDITABLE, &editable,
 					NULL );
 
 			g_return_if_fail( NA_IS_OBJECT_PROFILE( edited ));
 
-			if( readonly_item || !writable_provider ){
+			if( editable ){
+				nact_iconditions_tab_get_isfiledir( instance, &isfile, &isdir );
+				na_object_profile_set_isfiledir( edited, isfile, isdir );
+				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
+
+			} else if( gtk_toggle_button_get_active( button )){
 				g_signal_handlers_block_by_func(( gpointer ) button, on_isfiledir_toggled, instance );
 				isfile = na_object_profile_get_is_file( edited );
 				isdir = na_object_profile_get_is_dir( edited );
-				set_isfiledir( instance, isfile, isdir, readonly_item || !writable_provider );
+				set_isfiledir( instance, isfile, isdir, !editable );
 				g_signal_handlers_unblock_by_func(( gpointer ) button, on_isfiledir_toggled, instance );
-
-			} else if( gtk_toggle_button_get_active( button )){
-				nact_iconditions_tab_get_isfiledir( instance, &isfile, &isdir );
-				na_object_profile_set_isfiledir( edited, isfile, isdir );
-				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
 			}
 		}
 	}
@@ -515,30 +511,28 @@ on_matchcase_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
 {
 	NAObjectProfile *edited;
 	gboolean matchcase;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		if( edited ){
 
 			matchcase = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
+			if( editable ){
+				na_object_profile_set_matchcase( edited, matchcase );
+				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
+
+			} else {
 				g_signal_handlers_block_by_func(( gpointer ) button, on_matchcase_toggled, instance );
 				gtk_toggle_button_set_active( button, !matchcase );
 				g_signal_handlers_unblock_by_func(( gpointer ) button, on_matchcase_toggled, instance );
-
-			} else {
-				na_object_profile_set_matchcase( edited, matchcase );
-				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
 			}
 		}
 	}
@@ -570,29 +564,27 @@ on_multiple_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
 {
 	NAObjectProfile *edited;
 	gboolean multiple;
-	gboolean readonly_item;
-	gboolean writable_provider;
+	gboolean editable;
 
 	if( !st_on_selection_change ){
 
 		g_object_get(
 				G_OBJECT( instance ),
 				TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
-				TAB_UPDATABLE_PROP_READONLY_ITEM, &readonly_item,
-				TAB_UPDATABLE_PROP_WRITABLE_PROVIDER, &writable_provider,
+				TAB_UPDATABLE_PROP_EDITABLE, &editable,
 				NULL );
 
 		if( edited ){
 			multiple = gtk_toggle_button_get_active( button );
 
-			if( readonly_item || !writable_provider ){
+			if( editable ){
+				na_object_profile_set_multiple( edited, multiple );
+				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
+
+			} else {
 				g_signal_handlers_block_by_func(( gpointer ) button, on_multiple_toggled, instance );
 				gtk_toggle_button_set_active( button, !multiple );
 				g_signal_handlers_unblock_by_func(( gpointer ) button, on_multiple_toggled, instance );
-
-			} else {
-				na_object_profile_set_multiple( edited, multiple );
-				g_signal_emit_by_name( G_OBJECT( instance ), TAB_UPDATABLE_SIGNAL_ITEM_UPDATED, edited, FALSE );
 			}
 		}
 	}
diff --git a/nautilus-actions/nact/nact-main-menubar.c b/nautilus-actions/nact/nact-main-menubar.c
index b425eea..78cda20 100644
--- a/nautilus-actions/nact/nact-main-menubar.c
+++ b/nautilus-actions/nact/nact-main-menubar.c
@@ -628,14 +628,17 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 	is_level_zero_writable = na_pivot_is_level_zero_writable( pivot );
 
 	has_writable_providers = nact_window_has_writable_providers( NACT_WINDOW( window ));
+	g_debug( "%s: has_writable_providers=%s", thisfn, has_writable_providers ? "True":"False" );
+
 	has_modified_items = nact_main_window_has_modified_items( window );
+	g_debug( "%s: has_modified_items=%s", thisfn, has_modified_items ? "True":"False" );
 
 	selected_items = nact_iactions_list_bis_get_selected_items( NACT_IACTIONS_LIST( window ));
 	first_parent = selected_items && g_list_length( selected_items )
 			? ( NAObject * ) na_object_get_parent( selected_items->data )
 			: NULL;
 	is_first_parent_writable = first_parent
-			? nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( first_parent ))
+			? na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( first_parent ), NULL )
 			: is_level_zero_writable;
 
 	mis = ( MenubarIndicatorsStruct * ) g_object_get_data( G_OBJECT( window ), MENUBAR_PROP_INDICATORS );
@@ -685,7 +688,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 	enable_item( window, "NewProfileItem",
 			new_profile_enabled &&
 			selected_action != NULL &&
-			nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( selected_action )));
+			na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( selected_action ), NULL ));
 
 	/* save enabled if at least one item has been modified
 	 * or level-zero has been resorted and is writable
@@ -704,7 +707,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 	for( is = selected_items ; is ; is = is->next ){
 		parent_item = ( NAObject * ) na_object_get_parent( is->data );
 		if( parent_item ){
-			if( !nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( parent_item ))){
+			if( !na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( parent_item ), NULL )){
 				are_parents_writable = FALSE;
 				break;
 			}
@@ -742,7 +745,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 							? na_object_get_parent( selected_items->data )
 							: selected_items->data );
 			paste_enabled &= NA_IS_OBJECT_ACTION( selected_action );
-			paste_enabled &= nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( selected_action ));
+			paste_enabled &= na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( selected_action ), NULL );
 		}
 	} else {
 		paste_enabled &= has_writable_providers;
@@ -752,7 +755,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 			if( paste_enabled ){
 				parent_item = ( NAObject * ) na_object_get_parent( selected_item );
 				paste_enabled &= parent_item
-						? nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( parent_item ))
+						? na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( parent_item ), NULL )
 						: is_level_zero_writable;
 			}
 		} else {
@@ -779,7 +782,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 		if( paste_enabled ){
 			selected_action = NA_OBJECT( selected_items->data );
 			paste_enabled &= NA_IS_OBJECT_ACTION( selected_action );
-			paste_enabled &= nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( selected_action ));
+			paste_enabled &= na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( selected_action ), NULL );
 		}
 	} else {
 		paste_enabled &= has_writable_providers;
@@ -789,7 +792,7 @@ on_update_sensitivities( NactMainWindow *window, gpointer user_data )
 			if( paste_enabled ){
 				parent_item = ( NAObject * ) na_object_get_parent( selected_item );
 				paste_enabled &= parent_item
-						? nact_window_is_writable_item( NACT_WINDOW( window ), NA_OBJECT_ID( parent_item ))
+						? na_pivot_is_item_writable( pivot, NA_OBJECT_ITEM( parent_item ), NULL )
 						: is_level_zero_writable;
 			}
 		} else {
@@ -927,11 +930,10 @@ nact_main_menubar_save_items( NactMainWindow *window )
 	g_debug( "%s: window=%p", thisfn, ( void * ) window );
 	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
 
-	/* delete removed and modified items
+	/* remove deleted items
 	 * so that new actions with same id do not risk to be deleted later
 	 */
 	nact_main_window_remove_deleted( window );
-	nact_iactions_list_bis_removed_modified( NACT_IACTIONS_LIST( window ));
 
 	/* always write the level zero list of items
 	 * and reset the corresponding modification flag
@@ -975,8 +977,8 @@ save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
 	GList *subitems, *it;
 	NAObjectItem *parent;
 	gint pos;
-	NAIIOProvider *provider_before;
-	NAIIOProvider *provider_after;
+	NAIOProvider *provider_before;
+	NAIOProvider *provider_after;
 
 	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
 	g_return_if_fail( NA_IS_PIVOT( pivot ));
@@ -1028,6 +1030,8 @@ save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
 				na_pivot_add_item( pivot, dup_pivot );
 			}
 
+			nact_iactions_list_bis_removed_modified( NACT_IACTIONS_LIST( window ), item );
+
 			provider_after = na_object_get_provider( item );
 			if( provider_after != provider_before ){
 				g_signal_emit_by_name( window, TAB_UPDATABLE_SIGNAL_PROVIDER_CHANGED, item );
diff --git a/nautilus-actions/nact/nact-main-statusbar.c b/nautilus-actions/nact/nact-main-statusbar.c
index 1177d52..9e0852a 100644
--- a/nautilus-actions/nact/nact-main-statusbar.c
+++ b/nautilus-actions/nact/nact-main-statusbar.c
@@ -182,20 +182,26 @@ nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context )
  * Installs the corresponding tooltip.
  */
 void
-nact_main_statusbar_set_locked( NactMainWindow *window, gboolean provider, gboolean item )
+nact_main_statusbar_set_locked( NactMainWindow *window, gboolean readonly, gint reason )
 {
 	static const gchar *thisfn = "nact_main_statusbar_set_locked";
-	static const gchar *tooltip_provider = N_( "I/O Provider is locked down." );
-	static const gchar *tooltip_item = N_( "Item is read-only." );
+
+	static const gchar *tooltip_item_read_only = N_( "Item is read-only." );
+	static const gchar *tooltip_provider_not_willing_to = N_( "I/O provider is not willing to write." );
+	static const gchar *tooltip_provider_not_found = N_( "No writable I/O provider found." );
+	static const gchar *tooltip_provider_locked_by_admin = N_( "I/O provider has been locked down by an administrator." );
+	static const gchar *tooltip_provider_locked_by_user = N_( "I/O provider has been locked down by the user." );
+	static const gchar *tooltip_provider_no_api = N_( "I/O provider implementation lacks of required API." );
+	static const gchar *tooltip_config_locked = N_( "The whole configuration has been locked down by an administrator." );
+
 	GtkStatusbar *bar;
 	GtkFrame *frame;
 	GtkImage *image;
 	GdkPixbuf *pixbuf;
 	gchar *tooltip;
-	gchar *tmp;
 	gboolean set_pixbuf;
 
-	g_debug( "%s: window=%p, provider=%s, item=%s", thisfn, ( void * ) window, provider ? "True":"False", item ? "True":"False" );
+	g_debug( "%s: window=%p, readonly=%s, reason=%d", thisfn, ( void * ) window, readonly ? "True":"False", reason );
 
 	pixbuf = NULL;
 	set_pixbuf = TRUE;
@@ -207,23 +213,48 @@ nact_main_statusbar_set_locked( NactMainWindow *window, gboolean provider, gbool
 
 		tooltip = g_strdup( "" );
 
-		if( provider || item ){
+		if( readonly ){
 			gtk_image_set_from_file( image, LOCKED_IMAGE );
 			set_pixbuf = FALSE;
 
-			if( provider ){
-				g_free( tooltip );
-				tooltip = g_strdup( tooltip_provider );
-			}
-			if( item ){
-				if( provider ){
-					tmp = g_strdup_printf( "%s\n%s", tooltip, tooltip_item );
+			switch( reason ){
+				case NA_IIO_PROVIDER_STATUS_ITEM_READONLY:
+					g_free( tooltip );
+					tooltip = g_strdup( tooltip_item_read_only );
+					break;
+
+				case NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO:
+					g_free( tooltip );
+					tooltip = g_strdup( tooltip_provider_not_willing_to );
+					break;
+
+				case NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND:
 					g_free( tooltip );
-					tooltip = tmp;
-				} else {
+					tooltip = g_strdup( tooltip_provider_not_found );
+					break;
+
+				case NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_ADMIN:
 					g_free( tooltip );
-					tooltip = g_strdup( tooltip_item );
-				}
+					tooltip = g_strdup( tooltip_provider_locked_by_admin );
+					break;
+
+				case NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_USER:
+					g_free( tooltip );
+					tooltip = g_strdup( tooltip_provider_locked_by_user );
+					break;
+
+				case NA_IIO_PROVIDER_STATUS_NO_API:
+					g_free( tooltip );
+					tooltip = g_strdup( tooltip_provider_no_api );
+					break;
+
+				case NA_IIO_PROVIDER_STATUS_CONFIGURATION_LOCKED_BY_ADMIN:
+					g_free( tooltip );
+					tooltip = g_strdup( tooltip_config_locked );
+					break;
+
+				default:
+					break;
 			}
 		}
 
diff --git a/nautilus-actions/nact/nact-main-statusbar.h b/nautilus-actions/nact/nact-main-statusbar.h
index 6a6e682..eb80e90 100644
--- a/nautilus-actions/nact/nact-main-statusbar.h
+++ b/nautilus-actions/nact/nact-main-statusbar.h
@@ -46,7 +46,7 @@ void  nact_main_statusbar_initial_load_toplevel( NactMainWindow *window );
 void  nact_main_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status );
 void  nact_main_statusbar_display_with_timeout( NactMainWindow *window, const gchar *context, const gchar *status );
 void  nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context );
-void  nact_main_statusbar_set_locked( NactMainWindow *window, gboolean provider, gboolean item );
+void  nact_main_statusbar_set_locked( NactMainWindow *window, gboolean readonly, gint reason );
 
 G_END_DECLS
 
diff --git a/nautilus-actions/nact/nact-main-tab.h b/nautilus-actions/nact/nact-main-tab.h
index eadb52b..7955c4e 100644
--- a/nautilus-actions/nact/nact-main-tab.h
+++ b/nautilus-actions/nact/nact-main-tab.h
@@ -46,8 +46,8 @@
 #define TAB_UPDATABLE_PROP_EDITED_ACTION				"nact-tab-updatable-edited-action"
 #define TAB_UPDATABLE_PROP_EDITED_PROFILE				"nact-tab-updatable-edited-profile"
 #define TAB_UPDATABLE_PROP_SELECTED_ROW					"nact-tab-updatable-selected-row"
-#define TAB_UPDATABLE_PROP_READONLY_ITEM				"nact-tab-updatable-readonly-item"
-#define TAB_UPDATABLE_PROP_WRITABLE_PROVIDER			"nact-tab-updatable-writable-provider"
+#define TAB_UPDATABLE_PROP_EDITABLE						"nact-tab-updatable-editable"
+#define TAB_UPDATABLE_PROP_REASON						"nact-tab-updatable-reason"
 
 /* signals
  */
diff --git a/nautilus-actions/nact/nact-main-window.c b/nautilus-actions/nact/nact-main-window.c
index 0a654e6..fffa1f6 100644
--- a/nautilus-actions/nact/nact-main-window.c
+++ b/nautilus-actions/nact/nact-main-window.c
@@ -80,10 +80,13 @@ struct NactMainWindowPrivate {
 	 * it may be different of the row being currently selected.
 	 *
 	 * Can be null, and this implies that edited_profile is also null.
+	 *
+	 * 'editable_item' property is computed on selection change;
+	 * This is the real writability status of the item.
 	 */
 	NAObjectItem    *edited_item;
-	gboolean         readonly_item;
-	gboolean         writable_provider;
+	gboolean         editable;
+	gint             reason;
 
 	/**
 	 * Currently edited profile.
@@ -117,8 +120,8 @@ enum {
 	PROP_EDITED_ITEM = 1,
 	PROP_EDITED_PROFILE,
 	PROP_SELECTED_ROW,
-	PROP_READONLY_ITEM,
-	PROP_WRITABLE_PROVIDER
+	PROP_EDITABLE,
+	PROP_REASON
 };
 
 /* signals
@@ -328,18 +331,18 @@ class_init( NactMainWindowClass *klass )
 	g_object_class_install_property( object_class, PROP_SELECTED_ROW, spec );
 
 	spec = g_param_spec_boolean(
-			TAB_UPDATABLE_PROP_READONLY_ITEM,
-			"Read-only item ?",
-			"Whether the item itself is read-only", FALSE,
+			TAB_UPDATABLE_PROP_EDITABLE,
+			"Editable item ?",
+			"Whether the item will be able to be updated against its I/O provider", FALSE,
 			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
-	g_object_class_install_property( object_class, PROP_READONLY_ITEM, spec );
+	g_object_class_install_property( object_class, PROP_EDITABLE, spec );
 
-	spec = g_param_spec_boolean(
-			TAB_UPDATABLE_PROP_WRITABLE_PROVIDER,
-			"Writable provider",
-			"Whether the provider of the item is writable", TRUE,
+	spec = g_param_spec_int(
+			TAB_UPDATABLE_PROP_REASON,
+			"No edition reason",
+			"Why is this item not editable", 0, 255, 0,
 			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
-	g_object_class_install_property( object_class, PROP_WRITABLE_PROVIDER, spec );
+	g_object_class_install_property( object_class, PROP_REASON, spec );
 
 	klass->private = g_new0( NactMainWindowClassPrivate, 1 );
 
@@ -561,7 +564,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_main_window_instance_init";
 	NactMainWindow *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_MAIN_WINDOW( instance ));
 	self = NACT_MAIN_WINDOW( instance );
 
@@ -617,12 +621,12 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
 				g_value_set_pointer( value, self->private->selected_row );
 				break;
 
-			case PROP_READONLY_ITEM:
-				g_value_set_boolean( value, self->private->readonly_item );
+			case PROP_EDITABLE:
+				g_value_set_boolean( value, self->private->editable );
 				break;
 
-			case PROP_WRITABLE_PROVIDER:
-				g_value_set_boolean( value, self->private->writable_provider );
+			case PROP_REASON:
+				g_value_set_int( value, self->private->reason );
 				break;
 
 			default:
@@ -655,12 +659,12 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
 				self->private->selected_row = g_value_get_pointer( value );
 				break;
 
-			case PROP_READONLY_ITEM:
-				self->private->readonly_item = g_value_get_boolean( value );
+			case PROP_EDITABLE:
+				self->private->editable = g_value_get_boolean( value );
 				break;
 
-			case PROP_WRITABLE_PROVIDER:
-				self->private->writable_provider = g_value_get_boolean( value );
+			case PROP_REASON:
+				self->private->reason = g_value_get_int( value );
 				break;
 
 			default:
@@ -679,7 +683,7 @@ instance_dispose( GObject *window )
 	gint pos;
 	GList *it;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
 	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
 	self = NACT_MAIN_WINDOW( window );
 
@@ -816,8 +820,6 @@ nact_main_window_get_item( const NactMainWindow *window, const gchar *uuid )
  *    we can create any new actions, deleting them, and so on
  *    if we have eventually deleted all newly created actions, then the
  *    final count of modified actions should be zero... don't it ?
- *
- * Note also that we don't count invalid items as they are not saveable.
  */
 gboolean
 nact_main_window_has_modified_items( const NactMainWindow *window )
@@ -1122,6 +1124,7 @@ on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected
 	NactMainWindow *window;
 	NAObject *object;
 	gint count;
+	NAPivot *pivot;
 
 	count = g_slist_length( selected_items );
 
@@ -1134,7 +1137,11 @@ on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected
 		return;
 	}
 
-	nact_main_statusbar_set_locked( window, FALSE, FALSE );
+	window->private->selected_row = NULL;
+	window->private->edited_item = NULL;
+	window->private->editable = FALSE;
+	window->private->reason = 0;
+	nact_main_statusbar_set_locked( window, FALSE, 0 );
 
 	if( count == 1 ){
 		g_return_if_fail( NA_IS_OBJECT_ID( selected_items->data ));
@@ -1151,13 +1158,11 @@ on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected
 			set_current_profile( window, TRUE, selected_items );
 		}
 
-		window->private->readonly_item = na_object_is_readonly( window->private->edited_item );
-		window->private->writable_provider = nact_window_is_writable_provider( NACT_WINDOW( window ), window->private->edited_item );
-		nact_main_statusbar_set_locked( window, !window->private->writable_provider, window->private->readonly_item );
+		pivot = nact_window_get_pivot( NACT_WINDOW( instance ));
+		window->private->editable = na_pivot_is_item_writable( pivot, window->private->edited_item, &window->private->reason );
+		nact_main_statusbar_set_locked( window, !window->private->editable, window->private->reason );
 
 	} else {
-		window->private->selected_row = NULL;
-		window->private->edited_item = NULL;
 		set_current_object_item( window, selected_items );
 	}
 
@@ -1220,9 +1225,9 @@ set_current_profile( NactMainWindow *window, gboolean set_action, GSList *select
 	if( window->private->edited_profile && set_action ){
 
 		NAObjectAction *action = NA_OBJECT_ACTION( na_object_get_parent( window->private->edited_profile ));
+		NAPivot *pivot = nact_window_get_pivot( NACT_WINDOW( window ));
 		window->private->edited_item = NA_OBJECT_ITEM( action );
-		window->private->readonly_item = na_object_is_readonly( window->private->edited_item );
-		window->private->writable_provider = nact_window_is_writable_provider( NACT_WINDOW( window ), window->private->edited_item );
+		window->private->editable = na_pivot_is_item_writable( pivot, window->private->edited_item, &window->private->reason );
 	}
 }
 
diff --git a/nautilus-actions/nact/nact-providers-list.c b/nautilus-actions/nact/nact-providers-list.c
index 4c776d3..fd46049 100644
--- a/nautilus-actions/nact/nact-providers-list.c
+++ b/nautilus-actions/nact/nact-providers-list.c
@@ -73,7 +73,7 @@ typedef struct {
 
 static gboolean st_on_selection_change = FALSE;
 
-static void       init_view_setup_defaults( GtkTreeView *treeview, BaseWindow *window );
+static void       init_view_setup_providers( GtkTreeView *treeview, BaseWindow *window );
 static void       init_view_connect_signals( GtkTreeView *treeview, BaseWindow *window );
 static void       init_view_select_first_row( GtkTreeView *treeview );
 
@@ -173,14 +173,14 @@ nact_providers_list_init_view( GtkTreeView *treeview, BaseWindow *window )
 
 	g_object_set_data( G_OBJECT( window ), PROVIDERS_LIST_TREEVIEW, treeview );
 
-	init_view_setup_defaults( treeview, window );
+	init_view_setup_providers( treeview, window );
 	init_view_connect_signals( treeview, window );
 
 	init_view_select_first_row( treeview );
 }
 
 static void
-init_view_setup_defaults( GtkTreeView *treeview, BaseWindow *window )
+init_view_setup_providers( GtkTreeView *treeview, BaseWindow *window )
 {
 	NactApplication *application;
 	NAPivot *pivot;
@@ -188,7 +188,6 @@ init_view_setup_defaults( GtkTreeView *treeview, BaseWindow *window )
 	GList *providers, *iter;
 	GtkTreeIter row;
 	gchar *id, *libelle;
-	NAIIOProvider *instance;
 
 	model = GTK_LIST_STORE( gtk_tree_view_get_model( treeview ));
 
@@ -199,20 +198,32 @@ init_view_setup_defaults( GtkTreeView *treeview, BaseWindow *window )
 	for( iter = providers ; iter ; iter = iter->next ){
 
 		gtk_list_store_append( model, &row );
+
 		id = na_io_provider_get_id( NA_IO_PROVIDER( iter->data ));
-		instance = na_io_provider_get_provider( NA_IO_PROVIDER( iter->data ));
-		if( instance ){
-			libelle = na_io_provider_get_name( NA_IO_PROVIDER( iter->data ));
-		} else {
-			libelle = g_strdup_printf( "<%s: %s>", id, _( "unavailable I/O provider" ));
+		libelle = na_io_provider_get_name( NA_IO_PROVIDER( iter->data ));
+
+		if( !libelle || !g_utf8_strlen( libelle, -1 )){
+
+			g_free( libelle );
+			if( na_io_provider_get_provider( NA_IO_PROVIDER( iter->data ))){
+
+				/* i18n: default name when the I/O providers doesn't provide one */
+				libelle = g_strdup_printf( "<%s: %s>", id, _( "no name" ));
+			} else {
+
+				/* i18n: name displayed when the corresponding I/O provider is unavailable at runtime */
+				libelle = g_strdup_printf( "<%s: %s>", id, _( "unavailable I/O provider" ));
+			}
 		}
+
 		gtk_list_store_set( model, &row,
-				PROVIDER_READABLE_COLUMN, na_io_provider_is_readable_at_startup( NA_IO_PROVIDER( iter->data )),
-				PROVIDER_WRITABLE_COLUMN, na_io_provider_is_writable( NA_IO_PROVIDER( iter->data )),
+				PROVIDER_READABLE_COLUMN, na_io_provider_is_user_readable_at_startup( NA_IO_PROVIDER( iter->data ), pivot ),
+				PROVIDER_WRITABLE_COLUMN, na_io_provider_is_user_writable( NA_IO_PROVIDER( iter->data ), pivot ),
 				PROVIDER_LIBELLE_COLUMN, libelle,
 				PROVIDER_ID_COLUMN, id,
-				PROVIDER_PROVIDER_COLUMN, instance,
+				PROVIDER_PROVIDER_COLUMN, iter->data,
 				-1 );
+
 		g_free( libelle );
 		g_free( id );
 	}
@@ -313,6 +324,7 @@ nact_providers_list_save( BaseWindow *window )
 
 	plsd->order = g_slist_reverse( plsd->order );
 	na_iprefs_write_string_list( NA_IPREFS( pivot ), IO_PROVIDER_KEY_ORDER, plsd->order );
+	na_io_provider_reorder_providers_list( pivot );
 
 	na_utils_free_string_list( plsd->order );
 	g_free( plsd->path );
@@ -331,14 +343,9 @@ providers_list_save_iter( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter* i
 			PROVIDER_ID_COLUMN, &id,
 			PROVIDER_READABLE_COLUMN, &readable,
 			PROVIDER_WRITABLE_COLUMN, &writable,
+			PROVIDER_PROVIDER_COLUMN, &provider,
 			-1 );
 
-	provider = na_io_provider_find_provider_by_id( plsd->providers, id );
-	if( provider ){
-		na_io_provider_set_readable_at_startup( provider, readable );
-		na_io_provider_set_writable( provider, writable );
-	}
-
 	key = gconf_concat_dir_and_key( plsd->path, id );
 
 	entry = gconf_concat_dir_and_key( key, IO_PROVIDER_KEY_READABLE );
@@ -351,6 +358,7 @@ providers_list_save_iter( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter* i
 
 	plsd->order = g_slist_prepend( plsd->order, g_strdup( id ));
 
+	g_object_unref( provider );
 	g_free( id );
 	g_free( key );
 
@@ -502,22 +510,23 @@ on_down_clicked( GtkButton *button, BaseWindow *window )
 static void
 display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, GtkTreeView *treeview )
 {
-	NAIIOProvider *instance;
+	NAIOProvider *provider;
 	gchar *name;
 
-	gtk_tree_model_get( model, iter, PROVIDER_LIBELLE_COLUMN, &name, PROVIDER_PROVIDER_COLUMN, &instance, -1 );
+	gtk_tree_model_get( model, iter, PROVIDER_LIBELLE_COLUMN, &name, PROVIDER_PROVIDER_COLUMN, &provider, -1 );
 
 	g_object_set( cell, "style-set", FALSE, NULL );
 	g_object_set( cell, "foreground-set", FALSE, NULL );
 
-	if( !instance ){
+	if( !na_io_provider_get_provider( provider )){
+
 		g_object_set( cell, "style", PANGO_STYLE_ITALIC, "style-set", TRUE, NULL );
 		g_object_set( cell, "foreground", "grey", "foreground-set", TRUE, NULL );
 
-	} else {
-		g_object_unref( instance );
 	}
 
+	g_object_unref( provider );
+
 	g_object_set( cell, "text", name, NULL );
 	g_free( name );
 }
diff --git a/nautilus-actions/nact/nact-tree-model-dnd.c b/nautilus-actions/nact/nact-tree-model-dnd.c
index b31811a..b2b90a4 100644
--- a/nautilus-actions/nact/nact-tree-model-dnd.c
+++ b/nautilus-actions/nact/nact-tree-model-dnd.c
@@ -35,7 +35,6 @@
 #include <api/na-object-api.h>
 
 #include <runtime/na-iprefs.h>
-#include <runtime/na-io-provider.h>
 #include <runtime/na-utils.h>
 
 #include "nact-application.h"
@@ -939,7 +938,6 @@ is_parent_accept_new_childs( NactTreeModel *model, GtkTreePath *path )
 	NAObjectItem *parent_item;
 	NactApplication *application;
 	NAPivot *pivot;
-	NAIIOProvider *provider;
 	NactMainWindow *main_window;
 
 	accept_ok = FALSE;
@@ -966,11 +964,8 @@ is_parent_accept_new_childs( NactTreeModel *model, GtkTreePath *path )
 		parent_path = gtk_tree_path_copy( path );
 		if( gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &iter, parent_path )){
 			gtk_tree_model_get( GTK_TREE_MODEL( model ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &parent_item, -1 );
-			if( !na_object_is_readonly( parent_item )){
-				provider = na_object_get_provider( parent_item );
-				if( na_io_provider_is_willing_to_write( pivot, provider )){
-					accept_ok = TRUE;
-				}
+			if( na_pivot_is_item_writable( pivot, parent_item, NULL )){
+				accept_ok = TRUE;
 			}
 			g_object_unref( parent_item );
 		}
diff --git a/nautilus-actions/nact/nact-tree-model.c b/nautilus-actions/nact/nact-tree-model.c
index 4432845..b357cbf 100644
--- a/nautilus-actions/nact/nact-tree-model.c
+++ b/nautilus-actions/nact/nact-tree-model.c
@@ -213,7 +213,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_tree_model_instance_init";
 	NactTreeModel *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_TREE_MODEL( instance ));
 	self = NACT_TREE_MODEL( instance );
 
@@ -228,7 +229,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "nact_tree_model_instance_dispose";
 	NactTreeModel *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NACT_IS_TREE_MODEL( object ));
 	self = NACT_TREE_MODEL( object );
 
diff --git a/nautilus-actions/nact/nact-window.c b/nautilus-actions/nact/nact-window.c
index f878276..243f90f 100644
--- a/nautilus-actions/nact/nact-window.c
+++ b/nautilus-actions/nact/nact-window.c
@@ -125,7 +125,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "nact_window_instance_init";
 	NactWindow *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NACT_IS_WINDOW( instance ));
 	self = NACT_WINDOW( instance );
 
@@ -140,7 +141,7 @@ instance_dispose( GObject *window )
 	static const gchar *thisfn = "nact_window_instance_dispose";
 	NactWindow *self;
 
-	g_debug( "%s: window=%p", thisfn, ( void * ) window );
+	g_debug( "%s: window=%p (%s)", thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ));
 	g_return_if_fail( NACT_IS_WINDOW( window ));
 	self = NACT_WINDOW( window );
 
@@ -174,7 +175,10 @@ instance_finalize( GObject *window )
 }
 
 /**
- * Returns a pointer to the list of actions.
+ * nact_window_get_pivot:
+ * @window: this #NactWindow object.
+ *
+ * Returns a pointer to the #NAPivot object of the application.
  */
 NAPivot *
 nact_window_get_pivot( NactWindow *window )
@@ -197,73 +201,6 @@ nact_window_get_pivot( NactWindow *window )
 }
 
 /**
- * nact_window_is_writable_item:
- * @window: this #NactWindow instance.
- * @item: the item, which may be a profile, an action or a menu.
- *
- * Returns: %TRUE if the item is writable, %FALSE else.
- */
-gboolean
-nact_window_is_writable_item( NactWindow *window, const NAObjectId *item )
-{
-	gboolean writable;
-	NAObjectItem *parent;
-
-	writable = FALSE;
-
-	g_return_val_if_fail( NACT_IS_WINDOW( window ), writable );
-	g_return_val_if_fail( NA_IS_OBJECT_ID( item ), writable );
-
-	if( !window->private->dispose_has_run ){
-
-		parent = NA_IS_OBJECT_PROFILE( item ) ? na_object_get_parent( item ) : NA_OBJECT_ITEM( item );
-
-		writable =
-				!na_object_is_readonly( parent ) &&
-				nact_window_is_writable_provider( window, parent );
-	}
-
-	return( writable );
-}
-
-/**
- * nact_window_is_writable_provider:
- * @window: this #NactWindow instance.
- * @item: the current item.
- *
- * Returns: %TRUE if the item's provider is willing to write, %FALSE else.
- *
- * If the provider item has not yet any provider, i.e. has never been
- * saved elsewhere, then we test if we have at least one
- * willing-to-write provider.
- */
-gboolean
-nact_window_is_writable_provider( NactWindow *window, const NAObjectItem *item )
-{
-	gboolean writable;
-	NAPivot *pivot;
-	NAIIOProvider *provider;
-
-	writable = FALSE;
-
-	g_return_val_if_fail( NACT_IS_WINDOW( window ), writable );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), writable );
-
-	if( !window->private->dispose_has_run ){
-
-		pivot = nact_window_get_pivot( window );
-		provider = na_object_get_provider( item );
-		if( provider ){
-			writable = na_io_provider_is_willing_to_write( pivot, provider );
-		} else {
-			writable = nact_window_has_writable_providers( window );
-		}
-	}
-
-	return( writable );
-}
-
-/**
  * nact_window_has_writable_providers:
  * @window: this #NactWindow instance.
  *
@@ -274,7 +211,7 @@ nact_window_has_writable_providers( NactWindow *window )
 {
 	gboolean has_writables;
 	NAPivot *pivot;
-	NAIIOProvider *provider;
+	NAIOProvider *provider;
 
 	has_writables = FALSE;
 
@@ -287,7 +224,6 @@ nact_window_has_writable_providers( NactWindow *window )
 
 		if( provider ){
 			has_writables = TRUE;
-			g_object_unref( provider );
 		}
 	}
 
@@ -330,6 +266,9 @@ nact_window_save_item( NactWindow *window, NAObjectItem *item )
 
 		ret = na_pivot_write_item( pivot, item, &messages );
 
+		g_debug( "nact_window_save_item: ret=%d", ret );
+		na_object_dump( item );
+
 		if( messages ){
 			base_window_error_dlg(
 					BASE_WINDOW( window ),
@@ -339,7 +278,7 @@ nact_window_save_item( NactWindow *window, NAObjectItem *item )
 			na_utils_free_string_list( messages );
 		}
 
-		save_ok = ( ret == NA_IIO_PROVIDER_WRITE_OK );
+		save_ok = ( ret == NA_IIO_PROVIDER_CODE_OK );
 	}
 
 	return( save_ok );
@@ -384,7 +323,7 @@ nact_window_delete_item( NactWindow *window, const NAObjectItem *item )
 			na_utils_free_string_list( messages );
 		}
 
-		delete_ok = ( ret == NA_IIO_PROVIDER_WRITE_OK );
+		delete_ok = ( ret == NA_IIO_PROVIDER_CODE_OK );
 	}
 
 	return( delete_ok );
diff --git a/nautilus-actions/nact/nact-window.h b/nautilus-actions/nact/nact-window.h
index e577d23..62e8d57 100644
--- a/nautilus-actions/nact/nact-window.h
+++ b/nautilus-actions/nact/nact-window.h
@@ -75,8 +75,6 @@ GType    nact_window_get_type( void );
 
 NAPivot *nact_window_get_pivot( NactWindow *window );
 
-gboolean nact_window_is_writable_item( NactWindow *window, const NAObjectId *item );
-gboolean nact_window_is_writable_provider( NactWindow *window, const NAObjectItem *item );
 gboolean nact_window_has_writable_providers( NactWindow *window );
 
 gboolean nact_window_save_item( NactWindow *window, NAObjectItem *item );
diff --git a/nautilus-actions/plugin/nautilus-actions.c b/nautilus-actions/plugin/nautilus-actions.c
index 8c2e860..2293157 100644
--- a/nautilus-actions/plugin/nautilus-actions.c
+++ b/nautilus-actions/plugin/nautilus-actions.c
@@ -217,9 +217,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	/* initialize NAPivot and load actions through NAIIOProvider interface
 	 * forwarding notification messages from NAPivot to NautilusActions
 	 */
-	self->private->pivot = na_pivot_new(
-			!PIVOT_LOAD_DISABLED & !PIVOT_LOAD_INVALID,
-			PIVOT_IO_PROVIDER_AVAILABLE | PIVOT_IO_PROVIDER_READABLE_AT_STARTUP );
+	self->private->pivot = na_pivot_new( !PIVOT_LOAD_DISABLED & !PIVOT_LOAD_INVALID );
 
 	na_pivot_register_consumer( self->private->pivot, NA_IPIVOT_CONSUMER( self ));
 	na_pivot_set_automatic_reload( self->private->pivot, TRUE );
diff --git a/nautilus-actions/private/na-object-item-fn.h b/nautilus-actions/private/na-object-item-fn.h
index 16a95a0..504f990 100644
--- a/nautilus-actions/private/na-object-item-fn.h
+++ b/nautilus-actions/private/na-object-item-fn.h
@@ -44,44 +44,44 @@
 
 #include <gdk/gdk.h>
 
-#include <nautilus-actions/api/na-iio-provider.h>
+#include <runtime/na-io-provider.h>
 
 #include "na-object-item-class.h"
 
 G_BEGIN_DECLS
 
-void           na_object_item_free_items_list( GList *items );
+void          na_object_item_free_items_list( GList *items );
 
-gchar         *na_object_item_get_tooltip( const NAObjectItem *item );
-gchar         *na_object_item_get_icon( const NAObjectItem *item );
-GdkPixbuf     *na_object_item_get_pixbuf( const NAObjectItem *object );
-gint           na_object_item_get_position( const NAObjectItem *object, const NAObject *child );
-NAIIOProvider *na_object_item_get_provider( const NAObjectItem *item );
-void          *na_object_item_get_provider_data( const NAObjectItem *item );
-gboolean       na_object_item_is_enabled( const NAObjectItem *item );
-gboolean       na_object_item_is_readonly( const NAObjectItem *action );
-NAObject      *na_object_item_get_item( const NAObjectItem *item, const gchar *id );
-GList         *na_object_item_get_items_list( const NAObjectItem *item );
-guint          na_object_item_get_items_count( const NAObjectItem *item );
+gchar        *na_object_item_get_tooltip( const NAObjectItem *item );
+gchar        *na_object_item_get_icon( const NAObjectItem *item );
+GdkPixbuf    *na_object_item_get_pixbuf( const NAObjectItem *object );
+gint          na_object_item_get_position( const NAObjectItem *object, const NAObject *child );
+NAIOProvider *na_object_item_get_provider( const NAObjectItem *item );
+void         *na_object_item_get_provider_data( const NAObjectItem *item );
+gboolean      na_object_item_is_enabled( const NAObjectItem *item );
+gboolean      na_object_item_is_readonly( const NAObjectItem *action );
+NAObject     *na_object_item_get_item( const NAObjectItem *item, const gchar *id );
+GList        *na_object_item_get_items_list( const NAObjectItem *item );
+guint         na_object_item_get_items_count( const NAObjectItem *item );
 
-void           na_object_item_count_items( GList *items, gint *menus, gint *actions, gint *profiles, gboolean recurse );
+void          na_object_item_count_items( GList *items, gint *menus, gint *actions, gint *profiles, gboolean recurse );
 
-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_provider( NAObjectItem *item, const NAIIOProvider *provider );
-void           na_object_item_set_provider_data( NAObjectItem *item, const void *provider_data );
-void           na_object_item_set_enabled( NAObjectItem *item, gboolean enabled );
-void           na_object_item_set_readonly( NAObjectItem *action, gboolean readonly );
-void           na_object_item_set_items_list( NAObjectItem *item, 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_provider( NAObjectItem *item, const NAIOProvider *provider );
+void          na_object_item_set_provider_data( NAObjectItem *item, const void *provider_data );
+void          na_object_item_set_enabled( NAObjectItem *item, gboolean enabled );
+void          na_object_item_set_readonly( NAObjectItem *action, gboolean readonly );
+void          na_object_item_set_items_list( NAObjectItem *item, GList *items );
 
-void           na_object_item_append_item( NAObjectItem *object, const NAObject *item );
-void           na_object_item_insert_at( NAObjectItem *object, const NAObject *item, gint pos );
-void           na_object_item_insert_item( NAObjectItem *object, const NAObject *item, const NAObject *before );
-void           na_object_item_remove_item( NAObjectItem *object, const NAObject *item );
+void          na_object_item_append_item( NAObjectItem *object, const NAObject *item );
+void          na_object_item_insert_at( NAObjectItem *object, const NAObject *item, gint pos );
+void          na_object_item_insert_item( NAObjectItem *object, const NAObject *item, const NAObject *before );
+void          na_object_item_remove_item( NAObjectItem *object, const NAObject *item );
 
-GSList        *na_object_item_get_items_string_list( const NAObjectItem *item );
-GSList        *na_object_item_rebuild_items_list( const NAObjectItem *item );
-void           na_object_item_set_items_string_list( NAObjectItem *item, GSList *items );
+GSList       *na_object_item_get_items_string_list( const NAObjectItem *item );
+GSList       *na_object_item_rebuild_items_list( const NAObjectItem *item );
+void          na_object_item_set_items_string_list( NAObjectItem *item, GSList *items );
 
 G_END_DECLS
 
diff --git a/nautilus-actions/private/na-object-item-priv.h b/nautilus-actions/private/na-object-item-priv.h
index c78ce9f..f8991e3 100644
--- a/nautilus-actions/private/na-object-item-priv.h
+++ b/nautilus-actions/private/na-object-item-priv.h
@@ -40,31 +40,32 @@ G_BEGIN_DECLS
 /* private instance data
  */
 struct NAObjectItemPrivate {
-	gboolean       dispose_has_run;
+	gboolean      dispose_has_run;
 
 	/* object_item properties
 	 */
-	gchar         *tooltip;
-	gchar         *icon;
-	gboolean       enabled;
+	gchar        *tooltip;
+	gchar        *icon;
+	gboolean      enabled;
 
 	/* list of NAObjectId subitems
 	 * + list of id strings as readen from IIOProviders
 	 */
-	GList         *items;
-	GSList        *items_ids;
+	GList        *items;
+	GSList       *items_ids;
 
 	/* dynamically set when reading the actions from the I/O storage
-	 * subsystem
-	 * defaults to FALSE unless a write has already returned an error
+	 * subsystem; may be reset from FALSE to TRUE if a write operation
+	 * has returned an error.
+	 * defaults to FALSE for new, not yet written to a provider, items
 	 */
-	gboolean       read_only;
+	gboolean      read_only;
 
 	/* the original provider
 	 * required to be able to edit/delete the item
 	 */
-	NAIIOProvider *provider;
-	void          *provider_data;
+	NAIOProvider *provider;
+	void         *provider_data;
 };
 
 G_END_DECLS
diff --git a/nautilus-actions/private/na-object-item.c b/nautilus-actions/private/na-object-item.c
index dbd8898..9cd8ddf 100644
--- a/nautilus-actions/private/na-object-item.c
+++ b/nautilus-actions/private/na-object-item.c
@@ -173,7 +173,7 @@ class_init( NAObjectItemClass *klass )
 	spec = g_param_spec_pointer(
 			NAOBJECT_ITEM_PROP_PROVIDER,
 			"Original provider",
-			"Original provider of the NAObjectItem",
+			"Original NAIOProvider of the NAObjectItem",
 			G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 	g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_PROVIDER_ID, spec );
 
@@ -477,19 +477,18 @@ na_object_item_get_position( const NAObjectItem *object, const NAObject *child )
  * 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 the #NAIOProvider for this item, from which it has been
+ * initially readen, or to which it has been wrote in the case of a
+ * newly created item.
  *
- * Returns: a #NAIIOProvider object. The reference is
+ * Returns: a #NAIOProvider object. The reference is
  * owned by #NAPivot pivot and should not be g_object_unref() by the
  * caller.
  */
-NAIIOProvider *
+NAIOProvider *
 na_object_item_get_provider( const NAObjectItem *item )
 {
-	NAIIOProvider *provider = NULL;
+	NAIOProvider *provider = NULL;
 
 	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
 
@@ -553,6 +552,17 @@ na_object_item_is_enabled( const NAObjectItem *item )
  * original I/O storage subsystem ?
  *
  * Returns: %TRUE if the item is read-only, %FALSE else.
+ *
+ * This status is initially set when the item has been readen by the
+ * I/O provider. It indicates whether this item was able, at this time,
+ * to be updated, i.e. GConf keys (resp. .desktop file) was writable.
+ *
+ * It is an intrinsic status, not a composite one. Whether the item
+ * should eventually be considered as read-only also depends of the
+ * provider, the admin, the user...
+ *
+ * This status corresponds to the NA_IIO_PROVIDER_STATUS_ITEM_NOT_WRITABLE
+ * reason.
  */
 gboolean
 na_object_item_is_readonly( const NAObjectItem *item )
@@ -733,12 +743,12 @@ na_object_item_set_icon( NAObjectItem *item, const gchar *icon )
 /**
  * na_object_item_set_provider:
  * @item: the #NAObjectItem object to be updated.
- * @provider: the #NAIIOProvider to be set.
+ * @provider: the #NAIOProvider to be set.
  *
  * Sets the I/O provider for this #NAObjectItem.
  */
 void
-na_object_item_set_provider( NAObjectItem *item, const NAIIOProvider *provider )
+na_object_item_set_provider( NAObjectItem *item, const NAIOProvider *provider )
 {
 	g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
 
@@ -787,6 +797,8 @@ na_object_item_set_enabled( NAObjectItem *item, gboolean enabled )
  * @readonly: the indicator to be set.
  *
  * Sets whether the item is readonly.
+ *
+ * See #na_object_item_is_readonly() for a discussion about this status.
  */
 void
 na_object_item_set_readonly( NAObjectItem *item, gboolean readonly )
diff --git a/nautilus-actions/runtime/na-io-provider.c b/nautilus-actions/runtime/na-io-provider.c
index 9abb0e5..1ade804 100644
--- a/nautilus-actions/runtime/na-io-provider.c
+++ b/nautilus-actions/runtime/na-io-provider.c
@@ -54,8 +54,6 @@ struct NAIOProviderPrivate {
 	gboolean       dispose_has_run;
 	gchar         *id;
 	gchar         *name;
-	gboolean       read_at_startup;
-	gboolean       writable;
 	NAIIOProvider *provider;
 	gulong         item_changed_handler;
 };
@@ -88,9 +86,6 @@ static GList *merge_available_io_providers( const NAPivot *pivot, GList *ordered
 static void   io_provider_set_provider( const NAPivot *pivot, NAIOProvider *provider, NAIIOProvider *instance );
 static GList *add_io_providers_from_prefs( const NAPivot *pivot, GList *runtime_providers );
 
-static void   update_io_providers( const NAPivot *pivot, GList *runtime_providers );
-static GList *filter_io_providers( GList *runtime_providers, NAPivotIOProviderSet set );
-
 static void   dump( const NAIOProvider *provider );
 
 static GList *get_merged_items_list( const NAPivot *pivot, GList *providers, GSList **messages );
@@ -100,8 +95,6 @@ static GList *sort_tree( const NAPivot *pivot, GList *tree, GCompareFunc fn );
 static GList *filter_unwanted_items( const NAPivot *pivot, GList *merged );
 static GList *filter_unwanted_items_rec( GList *merged, gboolean load_disabled, gboolean load_invalid );
 
-static guint  try_write_item( const NAIIOProvider *instance, NAObjectItem *item, GSList **messages );
-
 GType
 na_io_provider_get_type( void )
 {
@@ -180,7 +173,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "na_io_provider_instance_init";
 	NAIOProvider *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NA_IS_IO_PROVIDER( instance ));
 	self = NA_IO_PROVIDER( instance );
 
@@ -189,8 +183,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private->dispose_has_run = FALSE;
 	self->private->id = NULL;
 	self->private->name = NULL;
-	self->private->read_at_startup = TRUE;
-	self->private->writable = TRUE;
 	self->private->provider = NULL;
 	self->private->item_changed_handler = 0;
 }
@@ -269,7 +261,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "na_io_provider_instance_dispose";
 	NAIOProvider *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NA_IS_IO_PROVIDER( object ));
 	self = NA_IO_PROVIDER( object );
 
@@ -355,6 +347,9 @@ na_io_provider_get_providers_list( const NAPivot *pivot )
 }
 
 /*
+ * @priority: the internal ids of IO providers id descending order of
+ * priority for writing new elements, as a string list
+ *
  * build the static list of I/O providers, depending of setup of NAPivot
  * doing required initializations
  */
@@ -363,9 +358,7 @@ setup_io_providers( const NAPivot *pivot, GSList *priority )
 {
 	GList *ordered_providers;
 	GList *merged_providers;
-	NAPivotIOProviderSet set;
 	GList *all_providers;
-	GList *filtered_providers;
 
 	g_return_if_fail( st_io_providers == NULL );
 
@@ -375,23 +368,10 @@ setup_io_providers( const NAPivot *pivot, GSList *priority )
 	/* merge with available I/O providers */
 	merged_providers = merge_available_io_providers( pivot, ordered_providers );
 
-	/* add providers found in prefs, in not stuck to those available at runtime */
-	set = na_pivot_get_io_provider_set( pivot );
-
-	if( set & PIVOT_IO_PROVIDER_AVAILABLE ){
-		all_providers = merged_providers;
-
-	} else {
-		all_providers = add_io_providers_from_prefs( pivot, merged_providers );
-	}
-
-	/* update all those providers from prefs */
-	update_io_providers( pivot, all_providers );
+	/* add providers found in prefs */
+	all_providers = add_io_providers_from_prefs( pivot, merged_providers );
 
-	/* filter if we don't want not readable or not writable */
-	filtered_providers = filter_io_providers( all_providers, set );
-
-	st_io_providers = filtered_providers;
+	st_io_providers = all_providers;
 }
 
 static GList *
@@ -515,63 +495,42 @@ add_io_providers_from_prefs( const NAPivot *pivot, GList *runtime_providers )
 	return( providers );
 }
 
-static void
-update_io_providers( const NAPivot *pivot, GList *providers )
-{
-	GConfClient *gconf;
-	gchar *path, *key, *entry;
-	GList *ip;
-
-	path = gconf_concat_dir_and_key( NAUTILUS_ACTIONS_GCONF_BASEDIR, IO_PROVIDER_KEY_ROOT );
-	gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
-
-	for( ip = providers ; ip ; ip = ip->next ){
-
-		key = gconf_concat_dir_and_key( path, ( const gchar * ) NA_IO_PROVIDER( ip->data )->private->id );
-
-		entry = gconf_concat_dir_and_key( key, IO_PROVIDER_KEY_READABLE );
-		NA_IO_PROVIDER( ip->data )->private->read_at_startup = na_gconf_utils_read_bool( gconf, entry, FALSE, TRUE );
-		g_free( entry );
-
-		entry = gconf_concat_dir_and_key( key, IO_PROVIDER_KEY_WRITABLE );
-		NA_IO_PROVIDER( ip->data )->private->writable = na_gconf_utils_read_bool( gconf, entry, FALSE, TRUE );
-		g_free( entry );
-
-		g_free( key );
-	}
-
-	g_free( path );
-}
-
-static GList *
-filter_io_providers( GList *providers, NAPivotIOProviderSet set )
+/**
+ * na_io_provider_reorder_providers_list:
+ * @pivot: the #NAPivot instance of the application.
+ *
+ * Reorder our global list of #NAIOProviders,after the user has reordered
+ * them in user preferences.
+ */
+void
+na_io_provider_reorder_providers_list( const NAPivot *pivot )
 {
-	GList *to_remove, *ip;
+	GSList *order, *io;
+	GList *new_list;
+	NAIOProvider *provider;
 
-	to_remove = NULL;
-	for( ip = providers ; ip ; ip = ip->next ){
+	new_list = NULL;
+	order = na_iprefs_read_string_list( NA_IPREFS( pivot ), IO_PROVIDER_KEY_ORDER, NULL );
 
-		if( set & PIVOT_IO_PROVIDER_READABLE_AT_STARTUP ){
-			if( !NA_IO_PROVIDER( ip->data )->private->read_at_startup ){
-				to_remove = g_list_prepend( to_remove, ip->data );
-			}
-		}
-
-		if( set & PIVOT_IO_PROVIDER_WRITABLE ){
-			if( !NA_IO_PROVIDER( ip->data )->private->writable ){
-				to_remove = g_list_prepend( to_remove, ip->data );
-			}
+	for( io = order ; io ; io = io->next ){
+		provider = na_io_provider_find_provider_by_id( st_io_providers, ( const gchar * ) io->data );
+		if( provider ){
+			st_io_providers = g_list_remove( st_io_providers, provider );
+			new_list = g_list_prepend( new_list, provider );
 		}
 	}
 
-	for( ip = to_remove ; ip ; ip = ip->next ){
-		providers = g_list_remove( providers, ip->data );
-		g_object_unref( ip->data );
-	}
+	st_io_providers = g_list_reverse( new_list );
 
-	return( providers );
+	na_utils_free_string_list( order );
 }
 
+/**
+ * na_io_provider_dump_providers_list:
+ * @providers: the list of #NAIOProvider to be dumped.
+ *
+ * Dumps the list of #NAIOProvider to debug output stream.
+ */
 void
 na_io_provider_dump_providers_list( GList *providers )
 {
@@ -592,8 +551,6 @@ dump( const NAIOProvider *provider )
 
 	g_debug( "%s:                   id=%s", thisfn, provider->private->id );
 	g_debug( "%s:                 name=%s", thisfn, provider->private->name );
-	g_debug( "%s:      read_at_startup=%s", thisfn, provider->private->read_at_startup ? "True":"False" );
-	g_debug( "%s:             writable=%s", thisfn, provider->private->writable ? "True":"False" );
 	g_debug( "%s:             provider=%p", thisfn, ( void * ) provider->private->provider );
 	g_debug( "%s: item_changed_handler=%ld", thisfn, provider->private->item_changed_handler );
 }
@@ -617,7 +574,9 @@ na_io_provider_find_provider_by_id( GList *providers, const gchar *id )
 	provider = NULL;
 
 	for( ip = providers ; ip && !provider ; ip = ip->next ){
+
 		if( !strcmp( NA_IO_PROVIDER( ip->data )->private->id, id )){
+
 			provider = NA_IO_PROVIDER( ip->data );
 		}
 	}
@@ -634,8 +593,8 @@ na_io_provider_find_provider_by_id( GList *providers, const gchar *id )
  * Loads the tree from I/O storage subsystems.
  *
  * Returns: a #GList of newly allocated objects as a hierarchical tree
- * in display order. This tree may contain #NAActionMenu menus and
- * #NAAction actions and their #NAActionProfile profiles.
+ * in display order. This tree contains #NAObjectMenu menus, along with
+ * #NAObjectAction actions and their #NAObjectProfile profiles.
  */
 GList *
 na_io_provider_read_items( const NAPivot *pivot, GSList **messages )
@@ -712,20 +671,23 @@ get_merged_items_list( const NAPivot *pivot, GList *providers, GSList **messages
 
 	for( ip = providers ; ip ; ip = ip->next ){
 
-		instance = NA_IO_PROVIDER( ip->data )->private->provider;
-		if( instance ){
+		if( na_io_provider_is_user_readable_at_startup( NA_IO_PROVIDER( ip->data ), pivot )){
 
-			if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_items ){
+			instance = NA_IO_PROVIDER( ip->data )->private->provider;
+			if( instance ){
 
-				list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_items( instance, messages );
+				if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_items ){
 
-				for( item = list ; item ; item = item->next ){
+					list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_items( instance, messages );
 
-					na_object_set_provider( item->data, instance );
-					na_object_dump( item->data );
-				}
+					for( item = list ; item ; item = item->next ){
+
+						na_object_set_provider( item->data, NA_IO_PROVIDER( ip->data ));
+						na_object_dump( item->data );
+					}
 
-				merged = g_list_concat( merged, list );
+					merged = g_list_concat( merged, list );
+				}
 			}
 		}
 	}
@@ -946,8 +908,9 @@ na_io_provider_get_name( const NAIOProvider *provider )
 }
 
 /**
- * na_io_provider_is_readable_at_startup:
+ * na_io_provider_is_user_readable_at_startup:
  * @provider: this #NAIOProvider.
+ * @pivot: the #NAPivot of the application.
  *
  * Returns: %TRUE is this I/O provider should be read at startup, and so
  * may participate to the global list of menus and actions.
@@ -959,24 +922,38 @@ na_io_provider_get_name( const NAIOProvider *provider )
  * the corresponding flag to %FALSE.
  */
 gboolean
-na_io_provider_is_readable_at_startup( const NAIOProvider *provider )
+na_io_provider_is_user_readable_at_startup( const NAIOProvider *provider, const NAPivot *pivot )
 {
 	gboolean to_be_read;
+	GConfClient *gconf;
+	gchar *path, *key, *entry;
 
 	to_be_read = FALSE;
-	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), to_be_read );
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
 
 	if( !provider->private->dispose_has_run ){
 
-		to_be_read = provider->private->read_at_startup;
+		gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
+
+		path = gconf_concat_dir_and_key( NAUTILUS_ACTIONS_GCONF_BASEDIR, IO_PROVIDER_KEY_ROOT );
+		key = gconf_concat_dir_and_key( path, provider->private->id );
+		entry = gconf_concat_dir_and_key( key, IO_PROVIDER_KEY_READABLE );
+
+		to_be_read = na_gconf_utils_read_bool( gconf, entry, FALSE, TRUE );
+
+		g_free( entry );
+		g_free( key );
+		g_free( path );
 	}
 
 	return( to_be_read );
 }
 
 /**
- * na_io_provider_is_writable:
+ * na_io_provider_is_user_writable:
  * @provider: this #NAIOProvider.
+ * @pivot: the #NAPivot of the application.
  *
  * Returns: %TRUE is this I/O provider is writable.
  *
@@ -984,22 +961,67 @@ na_io_provider_is_readable_at_startup( const NAIOProvider *provider )
  * will actually be writable or not.
  */
 gboolean
-na_io_provider_is_writable( const NAIOProvider *provider )
+na_io_provider_is_user_writable( const NAIOProvider *provider, const NAPivot *pivot )
 {
 	gboolean writable;
+	GConfClient *gconf;
+	gchar *path, *key, *entry;
 
 	writable = FALSE;
-	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), writable );
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
 
 	if( !provider->private->dispose_has_run ){
 
-		writable = provider->private->writable;
+		gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
+
+		path = gconf_concat_dir_and_key( NAUTILUS_ACTIONS_GCONF_BASEDIR, IO_PROVIDER_KEY_ROOT );
+		key = gconf_concat_dir_and_key( path, provider->private->id );
+		entry = gconf_concat_dir_and_key( key, IO_PROVIDER_KEY_WRITABLE );
+
+		writable = na_gconf_utils_read_bool( gconf, entry, FALSE, TRUE );
+
+		g_free( entry );
+		g_free( key );
+		g_free( path );
 	}
 
 	return( writable );
 }
 
 /**
+ * na_io_provider_is_locked_by_admin:
+ * @provider: this #NAIOProvider.
+ * @pivot: the #NAPivot of the application.
+ *
+ * Returns: %TRUE is this I/O provider has been locked by an admin.
+ */
+gboolean
+na_io_provider_is_locked_by_admin( const NAIOProvider *provider, const NAPivot *pivot )
+{
+	gboolean locked;
+	GConfClient *gconf;
+	gchar *path;
+
+	locked = FALSE;
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
+
+	if( !provider->private->dispose_has_run ){
+
+		gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
+
+		path = g_strdup_printf( "%s/mandatory/%s/locked", NAUTILUS_ACTIONS_GCONF_BASEDIR, provider->private->id );
+
+		locked = na_gconf_utils_read_bool( gconf, path, FALSE, FALSE );
+
+		g_free( path );
+	}
+
+	return( locked );
+}
+
+/**
  * na_io_provider_get_provider:
  * @provider: the #NAIOProvider object.
  *
@@ -1025,318 +1047,191 @@ na_io_provider_get_provider( const NAIOProvider *provider )
 }
 
 /**
- * na_io_provider_set_readable_at_startup:
- * @provider: the #NAIOProvider object.
- * @readable: whether this I/O provider may be read at startup.
+ * na_io_provider_is_willing_to_write:
+ * @provider: this #NAIOProvider.
  *
- * Set the 'read_a_startup' property.
+ * Returns: %TRUE is this I/O provider is willing to write.
  */
-void
-na_io_provider_set_readable_at_startup( NAIOProvider *provider, gboolean readable )
+gboolean
+na_io_provider_is_willing_to_write( const NAIOProvider *provider )
 {
-	g_return_if_fail( NA_IS_IO_PROVIDER( provider ));
+	gboolean willing_to;
+
+	willing_to = FALSE;
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), willing_to );
 
 	if( !provider->private->dispose_has_run ){
 
-		provider->private->read_at_startup = readable;
-	}
-}
+		if( provider->private->provider ){
 
-/**
- * na_io_provider_set_writable:
- * @provider: the #NAIOProvider object.
- * @writable: whether this I/O provider may be written.
- *
- * Set the 'writable' property.
- *
- * Note that this is only a user preference, and would not make writable
- * a NAIIOProvider which would either be read-only.
- */
-void
-na_io_provider_set_writable( NAIOProvider *provider, gboolean writable )
-{
-	g_return_if_fail( NA_IS_IO_PROVIDER( provider ));
+			g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), FALSE );
 
-	if( !provider->private->dispose_has_run ){
+			if( NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_willing_to_write ){
 
-		provider->private->writable = writable;
+				willing_to = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_willing_to_write( provider->private->provider );
+			}
+		}
 	}
+
+	return( willing_to );
 }
 
 /**
- * na_io_provider_get_provider_name:
- * @provider: the #NAIIOProvider whose name is to be returned.
+ * na_io_provider_is_able_to_write:
+ * @provider: this #NAIOProvider.
  *
- * Returns: a displayble name for the provider, as a newly allocated
- * string which should be g_free() by the caller.
+ * Returns: %TRUE is this I/O provider is willing to write.
  */
-gchar *
-na_io_provider_get_provider_name( const NAIIOProvider *provider )
+gboolean
+na_io_provider_is_able_to_write( const NAIOProvider *provider )
 {
-	gchar *name;
+	gboolean able_to;
 
-	name = NULL;
+	able_to = FALSE;
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), able_to );
 
-	if( NA_IIO_PROVIDER_GET_INTERFACE( provider )->get_name ){
-		name = NA_IIO_PROVIDER_GET_INTERFACE( provider )->get_name( provider );
-	} else {
-		name = g_strdup( "" );
-	}
+	if( !provider->private->dispose_has_run ){
 
-	return( name );
-}
+		if( provider->private->provider ){
 
-/**
- * na_io_provider_get_writable_provider:
- * @pivot: the #NAPivot object.
- *
- * Returns: the first willing to write I/O provider, or NULL.
- *
- * The returned provider should be g_object_unref() by the caller.
- */
-NAIIOProvider *
-na_io_provider_get_writable_provider( const NAPivot *pivot )
-{
-	NAIIOProvider *provider;
-	GList *providers, *ip;
+			g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), FALSE );
 
-	provider = NULL;
-	providers = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
+			if( NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write ){
 
-	for( ip = providers ; ip && !provider ; ip = ip->next ){
-		if( na_io_provider_is_willing_to_write( pivot, NA_IIO_PROVIDER( ip->data ))){
-			provider = NA_IIO_PROVIDER( ip->data );
-			g_object_ref( provider );
+				able_to = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write( provider->private->provider );
+			}
 		}
 	}
 
-	na_pivot_free_providers( providers );
-
-	return( provider );
+	return( able_to );
 }
 
 /**
- * na_io_provider_get_id:
- * @pivot: the current #NAPivot instance.
- * @provider: the #NAIIOProvider whose id is to be returned.
+ * na_io_provider_has_write_api:
+ * @provider: this #NAIOProvider.
  *
- * Returns: the provider's id as a newly allocated string which should
- * be g_free() by the caller, or NULL.
+ * Returns: %TRUE is the NAIIOProvider implements write and delete api.
  */
-#if 0
-gchar *
-na_io_provider_get_id( const NAPivot *pivot, const NAIIOProvider *provider )
+gboolean
+na_io_provider_has_write_api( const NAIOProvider *provider )
 {
-	gchar *id;
+	gboolean has_api;
 
-	id = NULL;
-	if( NA_IIO_PROVIDER_GET_INTERFACE( provider )->get_id ){
-		id = NA_IIO_PROVIDER_GET_INTERFACE( provider )->get_id( provider );
-	}
+	has_api = FALSE;
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), has_api );
 
-	return( id );
-}
-#endif
+	if( !provider->private->dispose_has_run ){
 
-/**
- * na_io_provider_get_version:
- * @pivot: the current #NAPivot instance.
- * @provider: the #NAIIOProvider whose id is to be returned.
- *
- * Returns: the API's version the provider supports.
- */
-guint
-na_io_provider_get_version( const NAPivot *pivot, const NAIIOProvider *provider )
-{
-	guint version;
+		if( provider->private->provider ){
+
+			g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), FALSE );
 
-	version = 1;
-	if( NA_IIO_PROVIDER_GET_INTERFACE( provider )->get_version ){
-		version = NA_IIO_PROVIDER_GET_INTERFACE( provider )->get_version( provider );
+			has_api =
+					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item &&
+					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item;
+		}
 	}
 
-	return( version );
+	return( has_api );
 }
 
 /**
- * na_io_provider_is_willing_to_write:
- * @pivot: the current #NAPivot instance.
- * @provider: the #NAIIOProvider whose name is to be returned.
+ * na_io_provider_get_writable_provider:
+ * @pivot: the #NAPivot object.
+ *
+ * Returns: the first willing and able to write I/O provider, or NULL.
  *
- * Returns: %TRUE if the I/O provider is willing to write _and_ it didn't
- * has been locked down by a sysadmin.
+ * The returned provider should not be g_object_unref() by the caller.
  */
-gboolean
-na_io_provider_is_willing_to_write( const NAPivot *pivot, const NAIIOProvider *provider )
+NAIOProvider *
+na_io_provider_get_writable_provider( const NAPivot *pivot )
 {
-	/*static const gchar *thisfn = "na_io_provider_is_willing_to_write";*/
-	gboolean writable;
-	gboolean locked;
-	/*GConfClient *gconf;
-	gchar *id;
-	gchar *key;*/
+	NAIOProvider *provider;
+	GList *providers, *ip;
 
-	writable = FALSE;
-	locked = FALSE;
+	providers = na_io_provider_get_providers_list( pivot );
+	provider = NULL;
 
-	if( NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_willing_to_write ){
+	for( ip = providers ; ip && !provider ; ip = ip->next ){
 
-		writable = NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_willing_to_write( provider );
+		if( na_io_provider_is_willing_to_write( NA_IO_PROVIDER( ip->data )) &&
+			na_io_provider_is_able_to_write( NA_IO_PROVIDER( ip->data )) &&
+			na_io_provider_is_user_writable( NA_IO_PROVIDER( ip->data ), pivot ) &&
+			!na_io_provider_is_locked_by_admin( NA_IO_PROVIDER( ip->data ), pivot ) &&
+			!na_pivot_is_configuration_locked_by_admin( pivot )){
 
-#if 0
-		if( writable ){
-			id = na_io_provider_get_id( pivot, provider );
-			key = g_strdup_printf( "%s/mandatory/%s/locked", NAUTILUS_ACTIONS_GCONF_BASEDIR, id );
-			gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
-			locked = na_gconf_utils_read_bool( gconf, key, TRUE, locked );
-			/*g_debug( "%s: id=%s, locked=%s", thisfn, id, locked ? "True":"False" );*/
-			g_free( key );
-			g_free( id );
+				provider = NA_IO_PROVIDER( ip->data );
 		}
-#endif
 	}
 
-	return( writable && !locked );
+	return( provider );
 }
 
 /**
  * na_io_provider_write_item:
- * @pivot: the #NAPivot object which owns the list of registered I/O
- * storage providers. if NULL, @action must already have registered
- * its own provider.
- * @item: a #NAObjectItem to be written by the storage subsystem.
+ * @provider: this #NAIOProvider object.
+ * @item: a #NAObjectItem to be written to the storage subsystem.
  * @messages: error messages.
  *
- * Writes an @item to a willing-to storage subsystem.
+ * Writes an @item to the storage subsystem.
  *
  * Returns: the NAIIOProvider return code.
+ *
+ * #NAPivot class, which should be the only caller of this function,
+ * has already check that this item is writable, i.e. that all conditions
+ * are met to be able to successfully write the item down to the
+ * storage subsystem.
  */
 guint
-na_io_provider_write_item( const NAPivot *pivot, NAObjectItem *item, GSList **messages )
+na_io_provider_write_item( const NAIOProvider *provider, const NAObjectItem *item, GSList **messages )
 {
 	static const gchar *thisfn = "na_io_provider_write_item";
 	guint ret;
-	NAIIOProvider *instance;
-	NAIIOProvider *bad_instance;
-	GList *providers, *ip;
 
-	g_debug( "%s: pivot=%p (%s), item=%p (%s), messages=%p", thisfn,
-			( void * ) pivot, G_OBJECT_TYPE_NAME( pivot ),
+	g_debug( "%s: provider=%p (%s), item=%p (%s), messages=%p", thisfn,
+			( void * ) provider, G_OBJECT_TYPE_NAME( provider ),
 			( void * ) item, G_OBJECT_TYPE_NAME( item ),
 			( void * ) messages );
 
-	g_return_val_if_fail(( NA_IS_PIVOT( pivot ) || !pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
-	ret = NA_IIO_PROVIDER_NOT_WRITABLE;
-	bad_instance = NULL;
-	*messages = NULL;
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), ret );
 
-	/* try to write to the original provider of the item
-	 */
-	instance = NA_IIO_PROVIDER( na_object_get_provider( item ));
-	if( instance ){
-		ret = try_write_item( instance, item, messages );
-		if( ret == NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE || ret == NA_IIO_PROVIDER_NOT_WRITABLE ){
-			bad_instance = instance;
-			instance = NULL;
-		}
-	}
-
-	/* else, search for a provider which is willing to write the item
-	 */
-	if( !instance && pivot ){
-		providers = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
-		for( ip = providers ; ip ; ip = ip->next ){
-
-			instance = NA_IIO_PROVIDER( ip->data );
-			if( !bad_instance || instance != bad_instance ){
-				ret = try_write_item( instance, item, messages );
-				if( ret == NA_IIO_PROVIDER_WRITE_OK ){
-					na_object_set_provider( item, instance );
-					break;
-				}
-			}
-		}
-		na_pivot_free_providers( providers );
-	}
+	ret = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item( provider->private->provider, item, messages );
 
 	return( ret );
 }
 
-static guint
-try_write_item( const NAIIOProvider *provider, NAObjectItem *item, GSList **messages )
-{
-	static const gchar *thisfn = "na_io_provider_try_write_item";
-	guint ret;
-
-	g_debug( "%s: provider=%p, item=%p, messages=%p",
-			thisfn, ( void * ) provider, ( void * ) item, ( void * ) messages );
-
-	if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_willing_to_write( provider )){
-		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
-	}
-
-	if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_writable( provider, item )){
-		return( NA_IIO_PROVIDER_NOT_WRITABLE );
-	}
-
-	if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_item ||
-		!NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_item ){
-		return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
-	}
-
-	ret = NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_item( provider, item, messages );
-	if( ret != NA_IIO_PROVIDER_WRITE_OK ){
-		return( ret );
-	}
-
-	return( NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_item( provider, item, messages ));
-}
-
 /**
  * na_io_provider_delete_item:
- * @pivot: the #NAPivot object which owns the list of registered I/O
- * storage providers.
+ * @provider: this #NAIOProvider object.
  * @item: the #NAObjectItem item to be deleted.
  * @messages: error messages.
  *
  * Deletes an item (action or menu) from the storage subsystem.
  *
  * Returns: the NAIIOProvider return code.
- *
- * Note that a new item, not already written to an I/O subsystem,
- * doesn't have any attached provider. We so do nothing and return OK...
  */
 guint
-na_io_provider_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages )
+na_io_provider_delete_item( const NAIOProvider *provider, const NAObjectItem *item, GSList **messages )
 {
 	static const gchar *thisfn = "na_io_provider_delete_item";
 	guint ret;
-	NAIIOProvider *instance;
 
-	g_debug( "%s: pivot=%p (%s), item=%p (%s), messages=%p", thisfn,
-			( void * ) pivot, G_OBJECT_TYPE_NAME( pivot ),
+	g_debug( "%s: provider=%p (%s), item=%p (%s), messages=%p", thisfn,
+			( void * ) provider, G_OBJECT_TYPE_NAME( provider ),
 			( void * ) item, G_OBJECT_TYPE_NAME( item ),
 			( void * ) messages );
 
-	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
-	*messages = NULL;
-	ret = NA_IIO_PROVIDER_NOT_WRITABLE;
-	instance = NA_IIO_PROVIDER( na_object_get_provider( item ));
-
-	if( instance ){
-		g_return_val_if_fail( NA_IS_IIO_PROVIDER( instance ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-
-		if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_item ){
-			ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_item( instance, item, messages );
-		}
+	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+	g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), ret );
 
-	} else {
-		ret = NA_IIO_PROVIDER_WRITE_OK;
-	}
+	ret = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item( provider->private->provider, item, messages );
 
 	return( ret );
 }
diff --git a/nautilus-actions/runtime/na-io-provider.h b/nautilus-actions/runtime/na-io-provider.h
index 4598938..4942cb2 100644
--- a/nautilus-actions/runtime/na-io-provider.h
+++ b/nautilus-actions/runtime/na-io-provider.h
@@ -79,31 +79,27 @@ GType          na_io_provider_get_type ( void );
 void           na_io_provider_terminate( void );
 
 GList         *na_io_provider_get_providers_list( const NAPivot *pivot );
+void           na_io_provider_reorder_providers_list( const NAPivot *pivot );
 void           na_io_provider_dump_providers_list( GList *providers );
+
 NAIOProvider  *na_io_provider_find_provider_by_id( GList *providers, const gchar *id );
 
 GList         *na_io_provider_read_items( const NAPivot *pivot, GSList **messages );
 
-gchar         *na_io_provider_get_id                ( const NAIOProvider *provider );
-gchar         *na_io_provider_get_name              ( const NAIOProvider *provider );
-gboolean       na_io_provider_is_readable_at_startup( const NAIOProvider *provider );
-gboolean       na_io_provider_is_writable           ( const NAIOProvider *provider );
-NAIIOProvider *na_io_provider_get_provider          ( const NAIOProvider *provider );
-
-void           na_io_provider_set_readable_at_startup( NAIOProvider *provider, gboolean readable );
-void           na_io_provider_set_writable           ( NAIOProvider *provider, gboolean writable );
-
-/* ... */
-
-NAIIOProvider *na_io_provider_get_writable_provider( const NAPivot *pivot );
-
-gchar     *na_io_provider_get_provider_name( const NAIIOProvider *provider );
+gchar         *na_io_provider_get_id                     ( const NAIOProvider *provider );
+gchar         *na_io_provider_get_name                   ( const NAIOProvider *provider );
+gboolean       na_io_provider_is_user_readable_at_startup( const NAIOProvider *provider, const NAPivot *pivot );
+gboolean       na_io_provider_is_user_writable           ( const NAIOProvider *provider, const NAPivot *pivot );
+gboolean       na_io_provider_is_locked_by_admin         ( const NAIOProvider *provider, const NAPivot *pivot );
+NAIIOProvider *na_io_provider_get_provider               ( const NAIOProvider *provider );
+gboolean       na_io_provider_is_willing_to_write        ( const NAIOProvider *provider );
+gboolean       na_io_provider_is_able_to_write           ( const NAIOProvider *provider );
+gboolean       na_io_provider_has_write_api              ( const NAIOProvider *provider );
 
-guint          na_io_provider_get_version( const NAPivot *pivot, const NAIIOProvider *provider );
-gboolean       na_io_provider_is_willing_to_write( const NAPivot *pivot, const NAIIOProvider *provider );
+NAIOProvider  *na_io_provider_get_writable_provider( const NAPivot *pivot );
 
-guint          na_io_provider_write_item( const NAPivot *pivot, NAObjectItem *item, GSList **messages );
-guint          na_io_provider_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages );
+guint          na_io_provider_write_item ( const NAIOProvider *provider, const NAObjectItem *item, GSList **messages );
+guint          na_io_provider_delete_item( const NAIOProvider *provider, const NAObjectItem *item, GSList **messages );
 
 G_END_DECLS
 
diff --git a/nautilus-actions/runtime/na-module.c b/nautilus-actions/runtime/na-module.c
index 44411bf..3a9c286 100644
--- a/nautilus-actions/runtime/na-module.c
+++ b/nautilus-actions/runtime/na-module.c
@@ -143,7 +143,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "na_module_instance_init";
 	NAModule *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NA_IS_MODULE( instance ));
 	self = NA_MODULE( instance );
 
@@ -158,7 +159,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "na_module_instance_dispose";
 	NAModule *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NA_IS_MODULE( object ));
 	self = NA_MODULE( object );
 
@@ -166,9 +167,6 @@ instance_dispose( GObject *object )
 
 		self->private->dispose_has_run = TRUE;
 
-		g_type_module_unuse( G_TYPE_MODULE( self ));
-
-		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
 			G_OBJECT_CLASS( st_parent_class )->dispose( object );
 		}
@@ -510,17 +508,19 @@ na_module_has_id( NAModule *module, const gchar *id )
  * na_module_release_modules:
  * @modules: the list of loaded modules.
  *
- * Release resources allocated to the loaded modules.
+ * Release resources allocated to the loaded modules on #NAPivot dispose.
  */
 void
 na_module_release_modules( GList *modules )
 {
-	GList *im;
+	GList *imod;
+	GList *iobj;
 
-	for( im = modules ; im ; im = im->next ){
-		/* GLib-GObject-WARNING **: gtypemodule.c:112:
-		 * unsolicitated invocation of g_object_dispose() on GTypeModule */
-		/*g_object_unref( NA_MODULE( im->data ));*/
+	for( imod = modules ; imod ; imod = imod->next ){
+
+		for( iobj = NA_MODULE( imod->data )->private->objects ; iobj ; iobj = iobj->next ){
+			g_object_unref( iobj->data );
+		}
 	}
 
 	g_list_free( modules );
diff --git a/nautilus-actions/runtime/na-pivot.c b/nautilus-actions/runtime/na-pivot.c
index 36223ee..cf27bd5 100644
--- a/nautilus-actions/runtime/na-pivot.c
+++ b/nautilus-actions/runtime/na-pivot.c
@@ -38,6 +38,7 @@
 #include <api/na-gconf-monitor.h>
 
 #include "na-io-provider.h"
+#include "na-gconf-utils.h"
 #include "na-iprefs.h"
 #include "na-module.h"
 #include "na-pivot.h"
@@ -52,36 +53,35 @@ struct NAPivotClassPrivate {
 /* private instance data
  */
 struct NAPivotPrivate {
-	gboolean             dispose_has_run;
+	gboolean           dispose_has_run;
 
-	NAPivotLoadableSet   loadable_set;
-	NAPivotIOProviderSet io_provider_set;
+	NAPivotLoadableSet loadable_set;
 
 	/* dynamically loaded modules (extension plugins)
 	 */
-	GList               *modules;
+	GList             *modules;
 
 	/* list of instances to be notified of repository updates
 	 * these are called 'consumers' of NAPivot
 	 */
-	GList               *consumers;
+	GList             *consumers;
 
 	/* configuration tree
 	 */
-	GList               *tree;
+	GList             *tree;
 
 	/* whether to automatically reload the whole configuration tree
 	 * when a modification is detected in one of the underlying I/O
 	 * storage subsystems
 	 * defaults to FALSE
 	 */
-	gboolean             automatic_reload;
-	GTimeVal             last_event;
-	guint                event_source_id;
+	gboolean           automatic_reload;
+	GTimeVal           last_event;
+	guint              event_source_id;
 
 	/* list of monitoring objects on runtime preferences
 	 */
-	GList               *monitors;
+	GList             *monitors;
 };
 
 /* signals
@@ -95,7 +95,6 @@ enum {
  */
 enum {
 	NAPIVOT_PROP_LOADABLE_SET_ID = 1,
-	NAPIVOT_PROP_IO_PROVIDER_SET_ID
 };
 
 static GObjectClass *st_parent_class = NULL;
@@ -197,13 +196,6 @@ class_init( NAPivotClass *klass )
 			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
 	g_object_class_install_property( object_class, NAPIVOT_PROP_LOADABLE_SET_ID, spec );
 
-	spec = g_param_spec_int(
-			NAPIVOT_PROP_IO_PROVIDER_SET,
-			"I/O providers set",
-			"The nature of the I/O providers we are concerned about", 0, INT_MAX, 0,
-			G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
-	g_object_class_install_property( object_class, NAPIVOT_PROP_IO_PROVIDER_SET_ID, spec );
-
 	klass->private = g_new0( NAPivotClassPrivate, 1 );
 
 	/* register the signal and its default handler
@@ -237,7 +229,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	static const gchar *thisfn = "na_pivot_instance_init";
 	NAPivot *self;
 
-	g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
 	g_return_if_fail( NA_IS_PIVOT( instance ));
 	self = NA_PIVOT( instance );
 
@@ -245,7 +238,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
 
 	self->private->dispose_has_run = FALSE;
 	self->private->loadable_set = 0;
-	self->private->io_provider_set = 0;
 	self->private->modules = NULL;
 	self->private->consumers = NULL;
 	self->private->tree = NULL;
@@ -269,10 +261,6 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
 				g_value_set_int( value, self->private->loadable_set );
 				break;
 
-			case NAPIVOT_PROP_IO_PROVIDER_SET_ID:
-				g_value_set_int( value, self->private->io_provider_set );
-				break;
-
 			default:
 				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
 				break;
@@ -295,10 +283,6 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
 				self->private->loadable_set = g_value_get_int( value );
 				break;
 
-			case NAPIVOT_PROP_IO_PROVIDER_SET_ID:
-				self->private->io_provider_set = g_value_get_int( value );
-				break;
-
 			default:
 				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
 				break;
@@ -312,7 +296,7 @@ instance_dispose( GObject *object )
 	static const gchar *thisfn = "na_pivot_instance_dispose";
 	NAPivot *self;
 
-	g_debug( "%s: object=%p", thisfn, ( void * ) object );
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NA_IS_PIVOT( object ));
 	self = NA_PIVOT( object );
 
@@ -372,7 +356,7 @@ instance_finalize( GObject *object )
  * #NAObjectItem-derived object.
  */
 NAPivot *
-na_pivot_new( NAPivotLoadableSet loadable, NAPivotIOProviderSet provider )
+na_pivot_new( NAPivotLoadableSet loadable )
 {
 	static const gchar *thisfn = "na_pivot_new";
 	NAPivot *pivot;
@@ -382,7 +366,6 @@ na_pivot_new( NAPivotLoadableSet loadable, NAPivotIOProviderSet provider )
 	pivot = g_object_new(
 			NA_PIVOT_TYPE,
 			NAPIVOT_PROP_LOADABLE_SET, loadable,
-			NAPIVOT_PROP_IO_PROVIDER_SET, provider,
 			NULL );
 
 	pivot->private->modules = na_module_load_modules();
@@ -408,7 +391,6 @@ na_pivot_dump( const NAPivot *pivot )
 	if( !pivot->private->dispose_has_run ){
 
 		g_debug( "%s:     loadable_set=%d", thisfn, pivot->private->loadable_set );
-		g_debug( "%s:  io_provider_set=%d", thisfn, pivot->private->io_provider_set );
 		g_debug( "%s:          modules=%p (%d elts)", thisfn, ( void * ) pivot->private->modules, g_list_length( pivot->private->modules ));
 		g_debug( "%s:        consumers=%p (%d elts)", thisfn, ( void * ) pivot->private->consumers, g_list_length( pivot->private->consumers ));
 		g_debug( "%s:             tree=%p (%d elts)", thisfn, ( void * ) pivot->private->tree, g_list_length( pivot->private->tree ));
@@ -682,54 +664,207 @@ na_pivot_remove_item( NAPivot *pivot, NAObject *item )
 }
 
 /**
- * na_pivot_delete_item:
+ * na_pivot_is_item_writable:
+ * @pivot: this #NAPivot object.
+ * @item: the #NAObjectItem to be written.
+ * @reason: the reason for what @item may not be writable.
+ *
+ * Returns: %TRUE: if @item is actually writable, given the current
+ * status of its provider, %FALSE else.
+ *
+ * For an item be actually writable:
+ * - the item must not be itself in a read-only store, which has been
+ *   checked when first reading it
+ * - the provider must be willing (resp. able) to write
+ * - the provider must not has been locked by the admin
+ * - the writability of the provider must not have been removed by the user
+ * - the whole configuration must not have been locked by the admin.
+ */
+gboolean
+na_pivot_is_item_writable( const NAPivot *pivot, const NAObjectItem *item, gint *reason )
+{
+	gboolean writable;
+	NAIOProvider *provider;
+	gboolean is_new;
+
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
+
+	writable = FALSE;
+	if( reason ){
+		*reason = NA_IIO_PROVIDER_STATUS_UNDETERMINED;
+	}
+
+	if( !pivot->private->dispose_has_run ){
+
+		writable = TRUE;
+		if( reason ){
+			*reason = NA_IIO_PROVIDER_STATUS_WRITABLE;
+		}
+
+		if( writable ){
+			if( na_object_is_readonly( item )){
+				writable = FALSE;
+				if( reason ){
+					*reason = NA_IIO_PROVIDER_STATUS_ITEM_READONLY;
+				}
+			}
+		}
+
+		if( writable ){
+			provider = na_object_get_provider( item );
+			if( provider ){
+				is_new = FALSE;
+				if( !na_io_provider_is_willing_to_write( provider )){
+					writable = FALSE;
+					if( reason ){
+						*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO;
+					}
+				}
+			} else {
+				is_new = TRUE;
+				provider = na_io_provider_get_writable_provider( pivot );
+				if( !provider ){
+					writable = FALSE;
+					if( reason ){
+						*reason = NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND;
+					}
+				}
+			}
+		}
+
+		if( writable ){
+			if( na_io_provider_is_locked_by_admin( provider, pivot )){
+				writable = FALSE;
+				if( reason ){
+					*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_ADMIN;
+				}
+			}
+		}
+
+		if( writable ){
+			if( is_new && !na_io_provider_is_user_writable( provider, pivot )){
+				writable = FALSE;
+				if( reason ){
+					*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_USER;
+				}
+			}
+		}
+
+		if( writable ){
+			if( na_pivot_is_configuration_locked_by_admin( pivot )){
+				writable = FALSE;
+				if( reason ){
+					*reason = NA_IIO_PROVIDER_STATUS_CONFIGURATION_LOCKED_BY_ADMIN;
+				}
+			}
+		}
+
+		if( writable ){
+			if( !na_io_provider_has_write_api( provider )){
+				writable = FALSE;
+				if( reason ){
+					*reason = NA_IIO_PROVIDER_STATUS_NO_API;
+				}
+			}
+		}
+	}
+
+	return( writable );
+}
+
+/**
+ * na_pivot_write_item:
  * @pivot: this #NAPivot instance.
- * @item: the #NAObjectItem to be deleted from the storage subsystem.
+ * @item: a #NAObjectItem to be written by the storage subsystem.
  * @messages: the I/O provider can allocate and store here its error
  * messages.
  *
- * Deletes an action from the I/O storage subsystem.
+ * Writes an item (an action or a menu).
  *
  * Returns: the #NAIIOProvider return code.
  */
 guint
-na_pivot_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages )
+na_pivot_write_item( const NAPivot *pivot, NAObjectItem *item, GSList **messages )
 {
-	guint ret = NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE;
+	guint ret;
+	gint reason;
+
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
-	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( messages, NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+	g_return_val_if_fail( messages, ret );
 
 	if( !pivot->private->dispose_has_run ){
-		ret = na_io_provider_delete_item( pivot, item, messages );
+
+		NAIOProvider *provider = na_object_item_get_provider( item );
+		if( !provider ){
+			provider = na_io_provider_get_writable_provider( pivot );
+
+			if( !provider ){
+				ret = NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND;
+
+			} else {
+				na_object_set_provider( item, provider );
+			}
+		}
+
+		if( provider ){
+
+			if( !na_pivot_is_item_writable( pivot, item, &reason )){
+				ret = ( guint ) reason;
+
+			} else {
+				ret = na_io_provider_write_item( provider, item, messages );
+			}
+		}
 	}
 
 	return( ret );
 }
 
 /**
- * na_pivot_write_item:
+ * na_pivot_delete_item:
  * @pivot: this #NAPivot instance.
- * @item: a #NAObjectItem to be written by the storage subsystem.
+ * @item: the #NAObjectItem to be deleted from the storage subsystem.
  * @messages: the I/O provider can allocate and store here its error
  * messages.
  *
- * Writes an item (an action or a menu).
+ * Deletes an action from the I/O storage subsystem.
  *
  * Returns: the #NAIIOProvider return code.
+ *
+ * Note that a new item, not already written to an I/O subsystem,
+ * doesn't have any attached provider. We so do nothing and return OK...
  */
 guint
-na_pivot_write_item( const NAPivot *pivot, NAObjectItem *item, GSList **messages )
+na_pivot_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages )
 {
-	guint ret = NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE;
+	guint ret;
+	gint reason;
+
+	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
-	g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
-	g_return_val_if_fail( messages, NA_IIO_PROVIDER_PROGRAM_ERROR );
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), ret );
+	g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), ret );
+	g_return_val_if_fail( messages, ret );
 
 	if( !pivot->private->dispose_has_run ){
-		ret = na_io_provider_write_item( pivot, item, messages );
+
+		NAIOProvider *provider = na_object_item_get_provider( item );
+		if( provider ){
+
+			if( !na_pivot_is_item_writable( pivot, item, &reason )){
+				ret = ( guint ) reason;
+
+			} else {
+				ret = na_io_provider_delete_item( provider, item, messages );
+			}
+
+		} else {
+			ret = NA_IIO_PROVIDER_CODE_OK;
+		}
 	}
 
 	return( ret );
@@ -828,28 +963,6 @@ na_pivot_is_invalid_loadable( const NAPivot *pivot )
 }
 
 /**
- * na_pivot_get_io_provider_set:
- * @pivot: this #NAPivot instance.
- *
- * Returns: the I/O providers we are concerned about.
- */
-NAPivotIOProviderSet
-na_pivot_get_io_provider_set( const NAPivot *pivot )
-{
-	NAPivotIOProviderSet set;
-
-	set = 0;
-	g_return_val_if_fail( NA_IS_PIVOT( pivot ), set );
-
-	if( !pivot->private->dispose_has_run ){
-
-		set = pivot->private->io_provider_set;
-	}
-
-	return( set );
-}
-
-/**
  * na_pivot_sort_alpha_asc:
  * @a: first #NAObjectId.
  * @b: second #NAObjectId.
@@ -906,20 +1019,14 @@ na_pivot_sort_alpha_desc( const NAObjectId *a, const NAObjectId *b )
 gboolean
 na_pivot_is_level_zero_writable( const NAPivot *pivot )
 {
-	/*static const gchar *thisfn = "na_pivot_is_level_zero_writable";*/
 	gboolean writable;
-	/*NAIIOProvider *provider;*/
 
 	writable = FALSE;
 	g_return_val_if_fail( NA_IS_PIVOT( pivot ), writable );
 
 	if( !pivot->private->dispose_has_run ){
-		/*provider = na_io_provider_get_provider( pivot, "na-gconf" );
-		if( provider ){
-			writable = na_io_provider_is_willing_to_write( pivot, provider );
-			g_debug( "%s: writable=%s", thisfn, writable ? "True":"False" );
-			g_object_unref( provider );
-		}*/
+
+		writable = !na_pivot_is_configuration_locked_by_admin( pivot );
 	}
 
 	return( writable );
@@ -958,6 +1065,36 @@ na_pivot_write_level_zero( const NAPivot *pivot, GList *items )
 	}
 }
 
+/**
+ * na_pivot_is_configuration_locked_by_admin:
+ * @pivot: this #NAPivot.
+ *
+ * Returns: %TRUE if the whole configuration has been locked by an
+ * administrator, %FALSE else.
+ */
+gboolean
+na_pivot_is_configuration_locked_by_admin( const NAPivot *pivot )
+{
+	gboolean locked;
+	GConfClient *gconf;
+	gchar *path;
+
+	locked = FALSE;
+	g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
+
+	if( !pivot->private->dispose_has_run ){
+
+		gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
+		path = gconf_concat_dir_and_key( NAUTILUS_ACTIONS_GCONF_BASEDIR, "mandatory/all/locked" );
+
+		locked = na_gconf_utils_read_bool( gconf, path, FALSE, FALSE );
+
+		g_free( path );
+	}
+
+	return( locked );
+}
+
 static NAObjectItem *
 get_item_from_tree( const NAPivot *pivot, GList *tree, const gchar *id )
 {
diff --git a/nautilus-actions/runtime/na-pivot.h b/nautilus-actions/runtime/na-pivot.h
index 2f7a2d3..861516d 100644
--- a/nautilus-actions/runtime/na-pivot.h
+++ b/nautilus-actions/runtime/na-pivot.h
@@ -121,66 +121,52 @@ typedef enum {
 }
 	NAPivotLoadableSet;
 
-/* Which are the I/O providers we are concerned about ?
- * NACT management user interface wants all
- * N-A plugin is only concerned about those are actually available at
- * runtime and marked as readable in the preferences (or not marked at all)
- * nautilus-actions-new wants those which are available and marked as
- * writable in the preferences (or not marked as all)
- */
-typedef enum {
-	PIVOT_IO_PROVIDER_AVAILABLE           = 1 << 0,
-	PIVOT_IO_PROVIDER_READABLE_AT_STARTUP = 1 << 1,
-	PIVOT_IO_PROVIDER_WRITABLE            = 1 << 2,
-	PIVOT_IO_PROVIDER_ALL                 = 0
-}
-	NAPivotIOProviderSet;
-
 /* these properties must be set at construction time
  */
 #define NAPIVOT_PROP_LOADABLE_SET		"na-pivot-prop-loadable-set"
-#define NAPIVOT_PROP_IO_PROVIDER_SET	"na-pivot-prop-io-provider-set"
 
-NAPivot             *na_pivot_new( NAPivotLoadableSet loadable, NAPivotIOProviderSet provider );
-void                 na_pivot_dump( const NAPivot *pivot );
+NAPivot      *na_pivot_new( NAPivotLoadableSet loadable );
+void          na_pivot_dump( const NAPivot *pivot );
 
 /* providers management of any NAIxxxxProvider interface
  */
-GList               *na_pivot_get_providers( const NAPivot *pivot, GType type );
-void                 na_pivot_free_providers( GList *providers );
+GList        *na_pivot_get_providers( const NAPivot *pivot, GType type );
+void          na_pivot_free_providers( GList *providers );
 
 /* menus/actions items management
  */
-void                 na_pivot_item_changed_handler( NAIIOProvider *provider, const gchar *id, NAPivot *pivot );
+void          na_pivot_item_changed_handler( NAIIOProvider *provider, const gchar *id, NAPivot *pivot );
+
+GList        *na_pivot_get_items( const NAPivot *pivot );
+void          na_pivot_load_items( NAPivot *pivot );
 
-GList               *na_pivot_get_items( const NAPivot *pivot );
-void                 na_pivot_load_items( NAPivot *pivot );
+void          na_pivot_add_item( NAPivot *pivot, const NAObjectItem *item );
+NAObjectItem *na_pivot_get_item( const NAPivot *pivot, const gchar *id );
+void          na_pivot_remove_item( NAPivot *pivot, NAObject *item );
 
-void                 na_pivot_add_item( NAPivot *pivot, const NAObjectItem *item );
-NAObjectItem        *na_pivot_get_item( const NAPivot *pivot, const gchar *id );
-void                 na_pivot_remove_item( NAPivot *pivot, NAObject *item );
+gboolean      na_pivot_is_item_writable( const NAPivot *pivot, const NAObjectItem *item, gint *reason );
 
-guint                na_pivot_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages );
-guint                na_pivot_write_item( const NAPivot *pivot, NAObjectItem *item, GSList **messages );
+guint         na_pivot_write_item( const NAPivot *pivot, NAObjectItem *item, GSList **messages );
+guint         na_pivot_delete_item( const NAPivot *pivot, const NAObjectItem *item, GSList **messages );
 
 /* NAIPivotConsumer interface management
  */
-void                 na_pivot_register_consumer( NAPivot *pivot, const NAIPivotConsumer *consumer );
+void          na_pivot_register_consumer( NAPivot *pivot, const NAIPivotConsumer *consumer );
 
 /* NAPivot properties and configuration
  */
-void                 na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload );
+void          na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload );
 
-gboolean             na_pivot_is_disable_loadable( const NAPivot *pivot );
-gboolean             na_pivot_is_invalid_loadable( const NAPivot *pivot );
+gboolean      na_pivot_is_disable_loadable( const NAPivot *pivot );
+gboolean      na_pivot_is_invalid_loadable( const NAPivot *pivot );
 
-NAPivotIOProviderSet na_pivot_get_io_provider_set( const NAPivot *pivot );
+gint          na_pivot_sort_alpha_asc( const NAObjectId *a, const NAObjectId *b );
+gint          na_pivot_sort_alpha_desc( const NAObjectId *a, const NAObjectId *b );
 
-gint                 na_pivot_sort_alpha_asc( const NAObjectId *a, const NAObjectId *b );
-gint                 na_pivot_sort_alpha_desc( const NAObjectId *a, const NAObjectId *b );
+gboolean      na_pivot_is_level_zero_writable( const NAPivot *pivot );
+void          na_pivot_write_level_zero( const NAPivot *pivot, GList *items );
 
-gboolean             na_pivot_is_level_zero_writable( const NAPivot *pivot );
-void                 na_pivot_write_level_zero( const NAPivot *pivot, GList *items );
+gboolean      na_pivot_is_configuration_locked_by_admin( const NAPivot *pivot );
 
 /* notification message from NAIIOProvider to NAPivot
  */
diff --git a/nautilus-actions/utils/nautilus-actions-new.c b/nautilus-actions/utils/nautilus-actions-new.c
index bbd6035..d0e30f0 100644
--- a/nautilus-actions/utils/nautilus-actions-new.c
+++ b/nautilus-actions/utils/nautilus-actions-new.c
@@ -371,26 +371,15 @@ static gboolean
 write_to_gconf( NAObjectAction *action, GSList **msg )
 {
 	NAPivot *pivot;
-	NAIIOProvider *provider;
 	guint ret;
 
-	ret = NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE;
+	pivot = na_pivot_new( PIVOT_LOAD_NONE );
 
-	pivot = na_pivot_new(
-			PIVOT_LOAD_NONE,
-			PIVOT_IO_PROVIDER_AVAILABLE | PIVOT_IO_PROVIDER_WRITABLE );
-
-	provider = na_io_provider_get_writable_provider( pivot );
-	if( provider ){
-
-		na_object_set_provider( action, NA_IIO_PROVIDER( provider ));
-		ret = na_io_provider_write_item( pivot, NA_OBJECT_ITEM( action ), msg );
-		g_object_unref( provider );
-	}
+	ret = na_pivot_write_item( pivot, NA_OBJECT_ITEM( action ), msg );
 
 	g_object_unref( pivot );
 
-	return( ret == NA_IIO_PROVIDER_WRITE_OK );
+	return( ret == NA_IIO_PROVIDER_CODE_OK );
 }
 
 /*
diff --git a/nautilus-actions/utils/nautilus-actions-run.c b/nautilus-actions/utils/nautilus-actions-run.c
index ec4615d..4cfb252 100644
--- a/nautilus-actions/utils/nautilus-actions-run.c
+++ b/nautilus-actions/utils/nautilus-actions-run.c
@@ -213,9 +213,7 @@ get_action( const gchar *id )
 
 	action = NULL;
 
-	pivot = na_pivot_new(
-			!PIVOT_LOAD_DISABLED & !PIVOT_LOAD_INVALID,
-			PIVOT_IO_PROVIDER_AVAILABLE | PIVOT_IO_PROVIDER_READABLE_AT_STARTUP );
+	pivot = na_pivot_new( !PIVOT_LOAD_DISABLED & !PIVOT_LOAD_INVALID );
 
 	na_pivot_load_items( pivot );
 



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