[nautilus-actions] Review I/O providers writability status management



commit e8e9e9754683006a223c9ccb84a67ec382d6739b
Author: Pierre Wieser <pwieser trychlos org>
Date:   Tue Feb 1 22:34:08 2011 +0100

    Review I/O providers writability status management

 ChangeLog                         |   21 ++
 src/api/na-iio-provider.h         |   36 ++--
 src/core/na-io-provider.c         |  560 +++++++++----------------------------
 src/core/na-io-provider.h         |   15 +-
 src/core/na-pivot.c               |   25 --
 src/core/na-pivot.h               |    2 -
 src/core/na-updater.c             |   81 ++----
 src/core/na-updater.h             |    2 +-
 src/nact/nact-main-menubar-edit.c |    4 +-
 src/nact/nact-main-window.c       |    2 +-
 10 files changed, 197 insertions(+), 551 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 008ca89..8f2fbdc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2011-02-01 Pierre Wieser <pwieser trychlos org>
+
+	Review I/O providers writability status management.
+
+	* src/api/na-iio-provider.h: Review writability reason.
+
+	* src/core/na-io-provider.c:
+	* src/core/na-io-provider.h
+	(na_io_provider_is_able_to_write, na_io_provider_is_willing_to_write):
+	Removed functions.
+	(na_io_provider_is_finally_writable): New function.
+
+	* src/core/na-pivot.c:
+	* src/core/na-pivot.h
+	(na_pivot_is_configuration_locked_by_admin): Removed function.
+
+	* src/core/na-updater.c
+	* src/core/na-updater.h (na_updater_is_item_writable):
+	* src/nact/nact-main-menubar-edit.c (get_deletables):
+	* src/nact/nact-main-window.c: Updated accordingly.
+
 2011-01-31 Pierre Wieser <pwieser trychlos org>
 
 	* src/nact/nact-menubar.c (nact_main_menubar_enable_item):
diff --git a/src/api/na-iio-provider.h b/src/api/na-iio-provider.h
index 7fe2b2f..7fb7d42 100644
--- a/src/api/na-iio-provider.h
+++ b/src/api/na-iio-provider.h
@@ -334,30 +334,30 @@ void  na_iio_provider_item_changed ( const NAIIOProvider *instance );
  */
 /**
  * NAIIOProviderWritabilityStatus:
- * @NA_IIO_PROVIDER_STATUS_UNDETERMINED:             undetermined.
- * @NA_IIO_PROVIDER_STATUS_WRITABLE:                 the item is writable.
- * @NA_IIO_PROVIDER_STATUS_ITEM_READONLY:            the item is read-only.
- * @NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO:  the provider is not willing to write this item,
- *                                                   or doest not implement the required interface.
- * @NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND:        the provider has not been found.
- * @NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_ADMIN: the provider has been locked by the administrator.
- * @NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_USER:  the provider has been locked by the user.
- * @NA_IIO_PROVIDER_STATUS_CONFIGURATION_LOCKED_BY_ADMIN: the whole configuration has been locked
- *                                                        by the administrator.
- * @NA_IIO_PROVIDER_STATUS_NO_API:                   no API has been found.
+ * @NA_IIO_PROVIDER_STATUS_WRITABLE:          item and i/o provider are writable.
+ * @NA_IIO_PROVIDER_STATUS_UNAVAILABLE:       unavailable i/o provider.
+ * @NA_IIO_PROVIDER_STATUS_INCOMPLETE_API:    i/o provider has an incomplete write api.
+ * @NA_IIO_PROVIDER_STATUS_NOT_WILLING_TO:    i/o provider is not willing to write.
+ * @NA_IIO_PROVIDER_STATUS_NOT_ABLE_TO:       i/o provider is not able to write.
+ * @NA_IIO_PROVIDER_STATUS_LOCKED_BY_ADMIN:   i/o provider has been locked by the administrator.
+ * @NA_IIO_PROVIDER_STATUS_LOCKED_BY_USER:    i/o provider has been locked by the user.
+ * @NA_IIO_PROVIDER_STATUS_ITEM_READONLY:     item is read-only.
+ * @NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND: no writable i/o provider found.
+ * @NA_IIO_PROVIDER_STATUS_UNDETERMINED:      unknwon reason (and probably a bug).
  *
  * The reasons for which an item may not be writable.
  */
 typedef enum {
-	NA_IIO_PROVIDER_STATUS_UNDETERMINED = 0,
-	NA_IIO_PROVIDER_STATUS_WRITABLE,
+	NA_IIO_PROVIDER_STATUS_WRITABLE = 0,
+	NA_IIO_PROVIDER_STATUS_UNAVAILABLE,
+	NA_IIO_PROVIDER_STATUS_INCOMPLETE_API,
+	NA_IIO_PROVIDER_STATUS_NOT_WILLING_TO,
+	NA_IIO_PROVIDER_STATUS_NOT_ABLE_TO,
+	NA_IIO_PROVIDER_STATUS_LOCKED_BY_ADMIN,
+	NA_IIO_PROVIDER_STATUS_LOCKED_BY_USER,
 	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_UNDETERMINED,
 	/*< private >*/
 	NA_IIO_PROVIDER_STATUS_LAST,
 }
diff --git a/src/core/na-io-provider.c b/src/core/na-io-provider.c
index 52fe556..b107f12 100644
--- a/src/core/na-io-provider.c
+++ b/src/core/na-io-provider.c
@@ -55,6 +55,8 @@ struct _NAIOProviderPrivate {
 	gchar         *id;
 	NAIIOProvider *provider;
 	gulong         item_changed_handler;
+	gboolean       writable;
+	guint          reason;
 };
 
 /* NAIOProvider properties
@@ -65,17 +67,20 @@ enum {
 
 #define IO_PROVIDER_PROP_ID				"na-io-provider-prop-id"
 
+static const gchar  *st_enter_bug    = N_( "Please, be kind enough to fill out a bug report on "
+											"https://bugzilla.gnome.org/enter_bug.cgi?product=nautilus-actions."; );
+
 static GObjectClass *st_parent_class = NULL;
 static GList        *st_io_providers = NULL;
 
-static GType  register_type( void );
-static void   class_init( NAIOProviderClass *klass );
-static void   instance_init( GTypeInstance *instance, gpointer klass );
-static void   instance_constructed( GObject *object );
-static void   instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void   instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
-static void   instance_dispose( GObject *object );
-static void   instance_finalize( GObject *object );
+static GType         register_type( void );
+static void          class_init( NAIOProviderClass *klass );
+static void          instance_init( GTypeInstance *instance, gpointer klass );
+static void          instance_constructed( GObject *object );
+static void          instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void          instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void          instance_dispose( GObject *object );
+static void          instance_finalize( GObject *object );
 
 #if 0
 static void          dump( const NAIOProvider *provider );
@@ -87,7 +92,8 @@ static GList        *io_providers_list_add_from_prefs( const NAPivot *pivot, GLi
 static GList        *io_providers_list_add_from_write_order( const NAPivot *pivot, GList *objects_list );
 static GList        *io_providers_list_append_object( const NAPivot *pivot, GList *list, NAIIOProvider *module, const gchar *id );
 static void          io_providers_list_set_module( const NAPivot *pivot, NAIOProvider *provider_object, NAIIOProvider *provider_module );
-static gboolean      is_really_writable( const NAIOProvider *provider, const NAPivot *pivot );
+static gboolean      is_conf_writable( const NAIOProvider *provider, const NAPivot *pivot, gboolean *mandatory );
+static gboolean      is_finally_writable( const NAIOProvider *provider, const NAPivot *pivot, guint *reason );
 static GList        *load_items_filter_unwanted_items( const NAPivot *pivot, GList *merged, guint loadable_set );
 static GList        *load_items_filter_unwanted_items_rec( GList *merged, guint loadable_set );
 static GList        *load_items_get_merged_list( const NAPivot *pivot, guint loadable_set, GSList **messages );
@@ -180,6 +186,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	self->private->id = NULL;
 	self->private->provider = NULL;
 	self->private->item_changed_handler = 0;
+	self->private->writable = FALSE;
+	self->private->reason = NA_IIO_PROVIDER_STATUS_UNAVAILABLE;
 }
 
 static void
@@ -313,15 +321,15 @@ na_io_provider_find_writable_io_provider( const NAPivot *pivot )
 	NAIOProvider *provider;
 
 	providers = na_io_provider_get_io_providers_list( pivot );
-	provider = NULL;
 
-	for( ip = providers ; ip && !provider ; ip = ip->next ){
-		if( is_really_writable( NA_IO_PROVIDER( ip->data ), pivot )){
-			provider = NA_IO_PROVIDER( ip->data );
+	for( ip = providers ; ip ; ip = ip->next ){
+		provider = ( NAIOProvider * ) ip->data;
+		if( provider->private->writable ){
+			return( provider );
 		}
 	}
 
-	return( provider );
+	return( NULL );
 }
 
 /*
@@ -534,39 +542,6 @@ na_io_provider_is_conf_readable( const NAIOProvider *provider, const NAPivot *pi
 }
 
 /*
- * na_io_provider_is_able_to_write:
- * @provider: this #NAIOProvider.
- *
- * Whether the NAIIOProvider is able to write is a runtime condition.
- *
- * Returns: %TRUE is this I/O provider is able to write.
- */
-gboolean
-na_io_provider_is_able_to_write( const NAIOProvider *provider )
-{
-	gboolean is_able_to;
-
-	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
-
-	is_able_to = FALSE;
-
-	if( !provider->private->dispose_has_run ){
-
-		if( provider->private->provider ){
-
-			g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), FALSE );
-
-			if( NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write ){
-
-				is_able_to = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write( provider->private->provider );
-			}
-		}
-	}
-
-	return( is_able_to );
-}
-
-/*
  * na_io_provider_is_conf_writable:
  * @provider: this #NAIOProvider.
  * @pivot: the #NAPivot application object.
@@ -588,7 +563,6 @@ gboolean
 na_io_provider_is_conf_writable( const NAIOProvider *provider, const NAPivot *pivot, gboolean *mandatory )
 {
 	gboolean is_writable;
-	gchar *group;
 
 	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
 	g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
@@ -597,52 +571,40 @@ na_io_provider_is_conf_writable( const NAIOProvider *provider, const NAPivot *pi
 
 	if( !provider->private->dispose_has_run ){
 
-		group = g_strdup_printf( "%s %s", NA_IPREFS_IO_PROVIDER_GROUP, provider->private->id );
-		is_writable = na_settings_get_boolean_ex(
-				na_pivot_get_settings( pivot ), group, NA_IPREFS_IO_PROVIDER_WRITABLE, NULL, mandatory );
-		g_free( group );
+		is_writable = is_conf_writable( provider, pivot, mandatory );
 	}
 
 	return( is_writable );
 }
 
-/*
- * na_io_provider_is_willing_to_write:
+/**
+ * na_io_provider_is_finally_writable:
  * @provider: this #NAIOProvider.
+ * @reason: if not %NULL, a pointer to a guint which will hold the reason.
  *
- * The 'willing_to_write' property is an intrinsic attribute of the NAIIOProvider
- * module. It depends on:
- * - whether it provides a 'willing_to_write' api which returns %TRUE (defaults
- *   to %FALSE)
- * - whether it has the needed API (is_able_to_write, write_item, delete_item)
- *
- * Returns: %TRUE is this I/O provider is willing to write.
+ * Returns: the current writability status of this I/O provider.
  */
 gboolean
-na_io_provider_is_willing_to_write( const NAIOProvider *provider )
+na_io_provider_is_finally_writable( const NAIOProvider *provider, guint *reason )
 {
-	gboolean is_willing_to;
+	gboolean is_writable;
 
+	if( reason ){
+		*reason = NA_IIO_PROVIDER_STATUS_UNDETERMINED;
+	}
 	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
 
-	is_willing_to = FALSE;
-
-	if( !provider->private->dispose_has_run &&
-		provider->private->provider ){
-
-		g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), FALSE );
+	is_writable = FALSE;
 
-		if( NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_willing_to_write &&
-			NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_willing_to_write( provider->private->provider )){
+	if( !provider->private->dispose_has_run ){
 
-			is_willing_to =
-					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write &&
-					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item &&
-					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item;
+		is_writable = provider->private->writable;
+		if( reason ){
+			*reason = provider->private->reason;
 		}
 	}
 
-	return( is_willing_to );
+	return( is_writable );
 }
 
 /*
@@ -907,32 +869,82 @@ static void
 io_providers_list_set_module( const NAPivot *pivot, NAIOProvider *provider_object, NAIIOProvider *provider_module )
 {
 	provider_object->private->provider = g_object_ref( provider_module );
+
 	provider_object->private->item_changed_handler =
 			g_signal_connect(
 					provider_module, IO_PROVIDER_SIGNAL_ITEM_CHANGED,
 					( GCallback ) na_pivot_on_item_changed_handler, ( gpointer ) pivot );
+
+	provider_object->private->writable =
+			is_finally_writable( provider_object, pivot, &provider_object->private->reason );
+}
+
+static gboolean
+is_conf_writable( const NAIOProvider *provider, const NAPivot *pivot, gboolean *mandatory )
+{
+	gchar *group;
+	gboolean is_writable;
+
+	group = g_strdup_printf( "%s %s", NA_IPREFS_IO_PROVIDER_GROUP, provider->private->id );
+	is_writable = na_settings_get_boolean_ex(
+			na_pivot_get_settings( pivot ), group, NA_IPREFS_IO_PROVIDER_WRITABLE, NULL, mandatory );
+	g_free( group );
+
+	return( is_writable );
 }
 
 /*
- * is_really_writable:
- * @provider: the #NAIOProvider provider.
- * @pivot: the #NAPivot instance.
- *
- * Returns: %TRUE if the @provider will be able to write proposed items,
- * %FALSE else.
- *
- * Note thay almost all checked conditions are themselves subject to race
- * conditions. Unless that (!), the caller can be (almost) sure that writings
- * will be possible when this function returns %TRUE.
+ * Evaluate the writability status for this I/O provider at load time
+ * This same status may later be reevaluated on demand.
  */
 static gboolean
-is_really_writable( const NAIOProvider *provider, const NAPivot *pivot )
+is_finally_writable( const NAIOProvider *provider, const NAPivot *pivot, guint *reason )
 {
+	gboolean writable;
+	gboolean is_writable, mandatory;
+
+	g_return_val_if_fail( reason, FALSE );
+
+	writable = FALSE;
+	*reason = NA_IIO_PROVIDER_STATUS_UNAVAILABLE;
+
+	if( provider->private->provider && NA_IS_IIO_PROVIDER( provider->private->provider )){
+
+		writable = TRUE;
+		*reason = NA_IIO_PROVIDER_STATUS_WRITABLE;
 
-	return( na_io_provider_is_willing_to_write( provider ) &&
-			na_io_provider_is_able_to_write( provider ) &&
-			na_io_provider_is_conf_writable( provider, pivot, NULL ) &&
-			!na_pivot_is_configuration_locked_by_admin( pivot ));
+		if( !NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_willing_to_write ||
+			!NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write ||
+			!NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item ||
+			!NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item ){
+
+				writable = FALSE;
+				*reason = NA_IIO_PROVIDER_STATUS_INCOMPLETE_API;
+
+		} else if( !NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_willing_to_write( provider->private->provider )){
+
+				writable = FALSE;
+				*reason = NA_IIO_PROVIDER_STATUS_NOT_WILLING_TO;
+
+		} else if( !NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->is_able_to_write( provider->private->provider )){
+
+				writable = FALSE;
+				*reason = NA_IIO_PROVIDER_STATUS_NOT_ABLE_TO;
+
+		} else {
+			is_writable = is_conf_writable( provider, pivot, &mandatory );
+			if( !is_writable ){
+				writable = FALSE;
+				if( mandatory ){
+					*reason = NA_IIO_PROVIDER_STATUS_LOCKED_BY_ADMIN;
+				} else {
+					*reason = NA_IIO_PROVIDER_STATUS_LOCKED_BY_USER;
+				}
+			}
+		}
+	}
+
+	return( writable );
 }
 
 static GList *
@@ -1154,324 +1166,6 @@ peek_provider_by_id( const GList *providers, const gchar *id )
 	return( provider );
 }
 
-#if 0
-/*
- * @priority: the internal ids of IO providers in 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
- */
-static void
-setup_io_providers( const NAPivot *pivot, GSList *priority )
-{
-	GList *ordered_providers;
-	GList *merged_providers;
-	GList *all_providers;
-
-	g_return_if_fail( st_io_providers == NULL );
-
-	/* allocate the ordered list */
-	ordered_providers = allocate_ordered_providers( priority );
-
-	/* merge with available I/O providers */
-	merged_providers = merge_available_io_providers( pivot, ordered_providers );
-
-	/* add providers found in prefs */
-	all_providers = add_io_providers_from_prefs( pivot, merged_providers );
-
-	st_io_providers = all_providers;
-}
-
-static GList *
-allocate_ordered_providers( GSList *priority )
-{
-	GSList *ip;
-	NAIOProvider *provider;
-	GList *providers;
-
-	providers = NULL;
-
-	for( ip = priority ; ip ; ip = ip->next ){
-
-		provider = g_object_new( NA_IO_PROVIDER_TYPE, IO_PROVIDER_PROP_ID, ( const gchar * ) ip->data, NULL );
-		providers = g_list_prepend( providers, provider );
-	}
-
-	return( g_list_reverse( providers ));
-}
-
-/*
- * merge the ordered list of I/O providers (which have only Id)
- * with those found available at runtime
- */
-static GList *
-merge_available_io_providers( const NAPivot *pivot, GList *ordered )
-{
-	static const gchar *thisfn = "na_io_provider_merge_available_io_providers";
-	GList *merged;
-	GList *module_objects, *im;
-	gchar *id;
-	NAIOProvider *provider;
-
-	merged = ordered;
-
-	module_objects = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
-	for( im = module_objects ; im ; im = im->next ){
-
-		id = NULL;
-		if( NA_IIO_PROVIDER_GET_INTERFACE( NA_IIO_PROVIDER( im->data ))->get_id ){
-			id = NA_IIO_PROVIDER_GET_INTERFACE( NA_IIO_PROVIDER( im->data ))->get_id( NA_IIO_PROVIDER( im->data ));
-
-		} else {
-			g_warning( "%s: NAIIOProvider %p doesn't support get_id() interface", thisfn, ( void * ) im->data );
-		}
-
-		provider = NULL;
-		if( id ){
-			provider = na_io_provider_find_provider_by_id( merged, id );
-
-			if( !provider ){
-				g_debug( "%s: no provider already allocated in ordered list for id=%s", thisfn, id );
-				provider = g_object_new( NA_IO_PROVIDER_TYPE, IO_PROVIDER_PROP_ID, id, NULL );
-				merged = g_list_append( merged, provider );
-
-			} else {
-				g_debug( "%s: found NAIOProvider=%p (NAIIOProvider=%p) for id=%s",
-						thisfn, ( void * ) provider, ( void * ) im->data, id );
-			}
-
-			io_provider_set_provider( provider, NA_IIO_PROVIDER( im->data ), pivot );
-
-			g_free( id );
-		}
-	}
-
-	na_pivot_free_providers( module_objects );
-
-	return( merged );
-}
-
-static void
-io_provider_set_provider( NAIOProvider *provider, NAIIOProvider *instance, const NAPivot *pivot )
-{
-	static const gchar *thisfn = "na_io_provider_set_provider";
-
-	g_return_if_fail( NA_IS_IO_PROVIDER( provider ));
-	g_return_if_fail( NA_IS_IIO_PROVIDER( instance ));
-
-	provider->private->provider = g_object_ref( instance );
-
-	if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->get_name ){
-		provider->private->name = NA_IIO_PROVIDER_GET_INTERFACE( instance )->get_name( instance );
-	} else {
-		g_warning( "%s: NAIIOProvider %p doesn't support get_name() interface", thisfn, ( void * ) instance );
-	}
-
-	provider->private->item_changed_handler =
-			g_signal_connect(
-					instance,
-					IO_PROVIDER_SIGNAL_ITEM_CHANGED,
-					( GCallback ) na_pivot_item_changed_handler,
-					( gpointer ) pivot );
-}
-
-static GList *
-add_io_providers_from_prefs( const NAPivot *pivot, GList *runtime_providers )
-{
-	gchar *path, *id;
-	GSList *ids, *iid;
-	GList *providers;
-	NAIOProvider *provider;
-
-	providers = runtime_providers;
-	path = gconf_concat_dir_and_key( IPREFS_GCONF_BASEDIR, IO_PROVIDER_KEY_ROOT );
-	gconf = na_iprefs_get_gconf_client( NA_IPREFS( pivot ));
-
-	ids = na_gconf_utils_get_subdirs( gconf, path );
-
-	for( iid = ids ; iid ; iid = iid->next ){
-		id = g_path_get_basename(( const gchar * ) iid->data );
-		provider = na_io_provider_find_provider_by_id( providers, id );
-
-		if( !provider ){
-			provider = g_object_new( NA_IO_PROVIDER_TYPE, IO_PROVIDER_PROP_ID, id, NULL );
-			providers = g_list_append( providers, provider );
-		}
-
-		g_free( id );
-	}
-
-	na_gconf_utils_free_subdirs( ids );
-	g_free( path );
-
-	return( providers );
-}
-
-/*
- * 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 )
-{
-	GSList *order, *io;
-	GList *new_list;
-	NAIOProvider *provider;
-
-	new_list = NULL;
-	order = na_iprefs_read_string_list( NA_IPREFS( pivot ), IO_PROVIDER_KEY_ORDER, NULL );
-
-	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 );
-		}
-	}
-
-	st_io_providers = g_list_reverse( new_list );
-
-	na_core_utils_slist_free( order );
-}
-
-/*
- * na_io_provider_is_user_readable_at_startup:
- * @provider: this #NAIOProvider.
- * @iprefs: an implementor of the #NAIPrefs interface.
- *
- * Returns: %TRUE is this I/O provider should be read at startup, and so
- * may participate to the global list of menus and actions.
- *
- * This is a user preference.
- * If the preference is not recorded, then it defaults to %TRUE.
- * This means that the user may adjust its personal configuration to
- * fully ignore menu/action items from a NAIIOProvider, just by setting
- * the corresponding flag to %FALSE.
- */
-gboolean
-na_io_provider_is_user_readable_at_startup( const NAIOProvider *provider, const NAIPrefs *iprefs )
-{
-	gboolean to_be_read;
-	GConfClient *gconf;
-	gchar *path, *key, *entry;
-
-	to_be_read = FALSE;
-	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), FALSE );
-	g_return_val_if_fail( NA_IS_IPREFS( iprefs ), FALSE );
-
-	if( !provider->private->dispose_has_run ){
-
-		gconf = na_iprefs_get_gconf_client( iprefs );
-
-		path = gconf_concat_dir_and_key( IPREFS_GCONF_BASEDIR, IO_PROVIDER_KEY_ROOT );
-		key = gconf_concat_dir_and_key( path, provider->private->id );
-		entry = gconf_concat_dir_and_key( key, NA_IPREFS_IO_PROVIDER_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_find_provider_by_id:
- * @providers: the current list of #NAIOProvider.
- * @id: the searched internal id.
- *
- * Returns: the searched #NAIOProvider, or %NULL if not found.
- *
- * The returned object is owned by #NAIOProvider class, and should not
- * be g_object_unref() by the user.
- */
-NAIOProvider *
-na_io_provider_find_provider_by_id( GList *providers, const gchar *id )
-{
-	NAIOProvider *provider;
-	GList *ip;
-
-	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 );
-		}
-	}
-
-	return( provider );
-}
-
-/*
- * na_io_provider_is_locked_by_admin:
- * @provider: this #NAIOProvider.
- * @iprefs: an implementor of the #NAIPrefs interface.
- *
- * 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 NAIPrefs *iprefs )
-{
-	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_IPREFS( iprefs ), FALSE );
-
-	if( !provider->private->dispose_has_run ){
-
-		gconf = na_iprefs_get_gconf_client( iprefs );
-
-		path = g_strdup_printf( "%s/mandatory/%s/locked", IPREFS_GCONF_BASEDIR, provider->private->id );
-
-		locked = na_gconf_utils_read_bool( gconf, path, FALSE, FALSE );
-
-		g_free( path );
-	}
-
-	return( locked );
-}
-
-/*
- * na_io_provider_has_write_api:
- * @provider: this #NAIOProvider.
- *
- * Returns: %TRUE is the NAIIOProvider implements write and delete api.
- */
-gboolean
-na_io_provider_has_write_api( const NAIOProvider *provider )
-{
-	gboolean has_api;
-
-	has_api = FALSE;
-	g_return_val_if_fail( NA_IS_IO_PROVIDER( provider ), has_api );
-
-	if( !provider->private->dispose_has_run ){
-
-		if( provider->private->provider ){
-
-			g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider->private->provider ), FALSE );
-
-			has_api =
-					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item &&
-					NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item;
-		}
-	}
-
-	return( has_api );
-}
-#endif
-
 /*
  * na_io_provider_write_item:
  * @provider: this #NAIOProvider object.
@@ -1503,6 +1197,7 @@ na_io_provider_write_item( const NAIOProvider *provider, const NAObjectItem *ite
 	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 );
+	g_return_val_if_fail( NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item, ret );
 
 	ret = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->write_item( provider->private->provider, item, messages );
 
@@ -1535,6 +1230,7 @@ na_io_provider_delete_item( const NAIOProvider *provider, const NAObjectItem *it
 	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 );
+	g_return_val_if_fail( NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item, ret );
 
 	ret = NA_IIO_PROVIDER_GET_INTERFACE( provider->private->provider )->delete_item( provider->private->provider, item, messages );
 
@@ -1598,42 +1294,46 @@ na_io_provider_get_readonly_tooltip( guint reason )
 	tooltip = NULL;
 
 	switch( reason ){
-		case NA_IIO_PROVIDER_STATUS_ITEM_READONLY:
-			tooltip = g_strdup( _( "Item is read-only." ));
+		/* item is writable, so tooltip is empty */
+		case NA_IIO_PROVIDER_STATUS_WRITABLE:
+			tooltip = g_strdup( "" );
 			break;
 
-		case NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO:
+		case NA_IIO_PROVIDER_STATUS_UNAVAILABLE:
+			tooltip = g_strdup( _( "Unavailable I/O provider." ));
+			break;
+
+		case NA_IIO_PROVIDER_STATUS_INCOMPLETE_API:
+			tooltip = g_strdup( _( "I/O provider implementation lacks of required API." ));
+			break;
+
+		case NA_IIO_PROVIDER_STATUS_NOT_WILLING_TO:
 			tooltip = g_strdup( _( "I/O provider is not willing to write." ));
 			break;
 
-		case NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND:
-			tooltip = g_strdup( _( "No writable I/O provider found." ));
+		case NA_IIO_PROVIDER_STATUS_NOT_ABLE_TO:
+			tooltip = g_strdup( _( "I/O provider announces itself as unable to write." ));
 			break;
 
-		case NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_ADMIN:
+		case NA_IIO_PROVIDER_STATUS_LOCKED_BY_ADMIN:
 			tooltip = g_strdup( _( "I/O provider has been locked down by an administrator." ));
 			break;
 
-		case NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_USER:
+		case NA_IIO_PROVIDER_STATUS_LOCKED_BY_USER:
 			tooltip = g_strdup( _( "I/O provider has been locked down by the user." ));
 			break;
 
-		case NA_IIO_PROVIDER_STATUS_NO_API:
-			tooltip = g_strdup( _( "I/O provider implementation lacks of required API." ));
-			break;
-
-		case NA_IIO_PROVIDER_STATUS_CONFIGURATION_LOCKED_BY_ADMIN:
-			tooltip = g_strdup( _( "The whole configuration has been locked down by an administrator." ));
+		case NA_IIO_PROVIDER_STATUS_ITEM_READONLY:
+			tooltip = g_strdup( _( "Item is read-only." ));
 			break;
 
-		/* item is writable, so tooltip is empty */
-		case 0:
-			tooltip = g_strdup( "" );
+		case NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND:
+			tooltip = g_strdup( _( "No writable I/O provider found." ));
 			break;
 
 		default:
-			tooltip = g_strdup_printf( _( "Item is not writable for an unknown reason (%d).\n" \
-					"Please, be kind enough to fill out a bug report on http://bugzilla.gnome.org."; ), reason );
+			tooltip = g_strdup_printf(
+					_( "Item is not writable for an unknown reason (%d).\n%s" ), reason, st_enter_bug );
 			break;
 	}
 
@@ -1660,8 +1360,7 @@ na_io_provider_get_return_code_label( guint code )
 			break;
 
 		case NA_IIO_PROVIDER_CODE_PROGRAM_ERROR:
-			label = g_strdup( _( "Program flow error.\n" \
-					"Please, be kind enough to fill out a bug report on http://bugzilla.gnome.org."; ));
+			label = g_strdup_printf( _( "Program flow error.\n%s" ), st_enter_bug );
 			break;
 
 		case NA_IIO_PROVIDER_CODE_NOT_WILLING_TO_RUN:
@@ -1681,8 +1380,7 @@ na_io_provider_get_return_code_label( guint code )
 			break;
 
 		default:
-			label = g_strdup_printf( _( "Unknown return code (%d).\n" \
-					"Please, be kind enough to fill out a bug report on http://bugzilla.gnome.org."; ), code );
+			label = g_strdup_printf( _( "Unknown return code (%d).\n%s" ), code, st_enter_bug );
 			break;
 	}
 
diff --git a/src/core/na-io-provider.h b/src/core/na-io-provider.h
index 8742127..4bcbf49 100644
--- a/src/core/na-io-provider.h
+++ b/src/core/na-io-provider.h
@@ -105,20 +105,17 @@ gchar        *na_io_provider_get_id             ( const NAIOProvider *provider )
 gchar        *na_io_provider_get_name           ( const NAIOProvider *provider );
 gboolean      na_io_provider_is_available       ( const NAIOProvider *provider );
 gboolean      na_io_provider_is_conf_readable   ( const NAIOProvider *provider, const NAPivot *pivot, gboolean *mandatory );
-gboolean      na_io_provider_is_able_to_write   ( const NAIOProvider *provider );
 gboolean      na_io_provider_is_conf_writable   ( const NAIOProvider *provider, const NAPivot *pivot, gboolean *mandatory );
-gboolean      na_io_provider_is_willing_to_write( const NAIOProvider *provider );
+gboolean      na_io_provider_is_finally_writable( const NAIOProvider *provider, guint *reason );
 
 GList        *na_io_provider_load_items( const NAPivot *pivot, guint loadable_set, 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 );
+guint         na_io_provider_duplicate_data( const NAIOProvider *provider, NAObjectItem *dest, const NAObjectItem *source, 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 );
-guint          na_io_provider_duplicate_data( const NAIOProvider *provider, NAObjectItem *dest, const NAObjectItem *source, GSList **messages );
-
-gchar         *na_io_provider_get_readonly_tooltip( guint reason );
-gchar         *na_io_provider_get_return_code_label( guint code );
+gchar        *na_io_provider_get_readonly_tooltip ( guint reason );
+gchar        *na_io_provider_get_return_code_label( guint code );
 
 G_END_DECLS
 
diff --git a/src/core/na-pivot.c b/src/core/na-pivot.c
index 93a2df7..45ecf87 100644
--- a/src/core/na-pivot.c
+++ b/src/core/na-pivot.c
@@ -773,31 +773,6 @@ na_pivot_set_loadable( NAPivot *pivot, guint loadable )
 	}
 }
 
-/*
- * 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;
-
-	g_return_val_if_fail( NA_IS_PIVOT( pivot ), TRUE );
-
-	locked = TRUE;
-
-	if( !pivot->private->dispose_has_run ){
-
-		/* TODO: na_pivot_is_configuration_locked_by_admin */
-		locked = FALSE;
-	}
-
-	return( locked );
-}
-
 #if 0
 static void
 on_io_provider_prefs_changed( GConfClient *client, guint cnxn_id, GConfEntry *entry, NAPivot *pivot )
diff --git a/src/core/na-pivot.h b/src/core/na-pivot.h
index fcc8ce8..3f356f7 100644
--- a/src/core/na-pivot.h
+++ b/src/core/na-pivot.h
@@ -169,8 +169,6 @@ NASettings   *na_pivot_get_settings     ( const NAPivot *pivot );
 void          na_pivot_set_automatic_reload            ( NAPivot *pivot, gboolean reload );
 void          na_pivot_set_loadable                    ( NAPivot *pivot, guint loadable );
 
-gboolean      na_pivot_is_configuration_locked_by_admin( const NAPivot *pivot );
-
 G_END_DECLS
 
 #endif /* __CORE_NA_PIVOT_H__ */
diff --git a/src/core/na-updater.c b/src/core/na-updater.c
index 71b6a7c..77216fa 100644
--- a/src/core/na-updater.c
+++ b/src/core/na-updater.c
@@ -299,12 +299,14 @@ na_updater_remove_item( NAUpdater *updater, NAObject *item )
  * - 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.
+ * - the provider must not has been locked by the admin, nor by the user
+ *
+ * Note that this function does not consider if the item is to be written
+ * at the level zero of the tree, which may be a mandatory preference
+ * (i.e. locked by an admin), and so make this item unwritable.
  */
 gboolean
-na_updater_is_item_writable( const NAUpdater *updater, const NAObjectItem *item, gint *reason )
+na_updater_is_item_writable( const NAUpdater *updater, const NAObjectItem *item, guint *reason )
 {
 	gboolean writable;
 	NAIOProvider *provider;
@@ -324,6 +326,13 @@ na_updater_is_item_writable( const NAUpdater *updater, const NAObjectItem *item,
 			*reason = NA_IIO_PROVIDER_STATUS_WRITABLE;
 		}
 
+		/* Writability status of the item has been determined at load time
+		 * (cf. e.g. io-desktop/nadp-reader.c:read_done_item_is_writable()).
+		 * Though I'm plenty conscious that this status is subject to many
+		 * changes during the life of the item (e.g. by modifying permissions
+		 * on the underlying store), it is just simpler to not reevaluate
+		 * this status each time we need it
+		 */
 		if( writable ){
 			if( na_object_is_readonly( item )){
 				writable = FALSE;
@@ -336,38 +345,7 @@ na_updater_is_item_writable( const NAUpdater *updater, const NAObjectItem *item,
 		if( writable ){
 			provider = na_object_get_provider( item );
 			if( provider ){
-				if( !na_io_provider_is_willing_to_write( provider )){
-					writable = FALSE;
-					if( reason ){
-						*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO;
-					}
-				} else if( !na_io_provider_is_able_to_write( provider )){
-					writable = FALSE;
-					if( reason ){
-						/* TODO: found a reason */
-						*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_NOT_WILLING_TO;
-					}
-				/*} else if( na_io_provider_is_locked_by_admin( provider, NA_IPREFS( updater ))){
-					writable = FALSE;
-					if( reason ){
-						*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_ADMIN;
-					}*/
-				} else if( !na_io_provider_is_conf_writable( provider, NA_PIVOT( updater ), NULL )){
-					writable = FALSE;
-					if( reason ){
-						*reason = NA_IIO_PROVIDER_STATUS_PROVIDER_LOCKED_BY_USER;
-					}
-				} else if( na_pivot_is_configuration_locked_by_admin( NA_PIVOT( updater ))){
-					writable = FALSE;
-					if( reason ){
-						*reason = NA_IIO_PROVIDER_STATUS_CONFIGURATION_LOCKED_BY_ADMIN;
-					}
-				/*} else if( !na_io_provider_has_write_api( provider )){
-					writable = FALSE;
-					if( reason ){
-						*reason = NA_IIO_PROVIDER_STATUS_NO_API;
-					}*/
-				}
+				writable = na_io_provider_is_finally_writable( provider, reason );
 
 			/* the get_writable_provider() api already takes above checks
 			 */
@@ -401,7 +379,6 @@ guint
 na_updater_write_item( const NAUpdater *updater, NAObjectItem *item, GSList **messages )
 {
 	guint ret;
-	gint reason;
 
 	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
@@ -412,24 +389,14 @@ na_updater_write_item( const NAUpdater *updater, NAObjectItem *item, GSList **me
 	if( !updater->private->dispose_has_run ){
 
 		NAIOProvider *provider = na_object_get_provider( item );
+
 		if( !provider ){
 			provider = na_io_provider_find_writable_io_provider( NA_PIVOT( updater ));
-
-			if( !provider ){
-				ret = NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND;
-
-			} else {
-				na_object_set_provider( item, provider );
-			}
+			g_return_val_if_fail( provider, NA_IIO_PROVIDER_STATUS_NO_PROVIDER_FOUND );
 		}
 
 		if( provider ){
-			if( !na_updater_is_item_writable( updater, item, &reason )){
-				ret = ( guint ) reason;
-
-			} else {
-				ret = na_io_provider_write_item( provider, item, messages );
-			}
+			ret = na_io_provider_write_item( provider, item, messages );
 		}
 	}
 
@@ -454,7 +421,6 @@ guint
 na_updater_delete_item( const NAUpdater *updater, const NAObjectItem *item, GSList **messages )
 {
 	guint ret;
-	gint reason;
 
 	ret = NA_IIO_PROVIDER_CODE_PROGRAM_ERROR;
 
@@ -465,18 +431,9 @@ na_updater_delete_item( const NAUpdater *updater, const NAObjectItem *item, GSLi
 	if( !updater->private->dispose_has_run ){
 
 		NAIOProvider *provider = na_object_get_provider( item );
-		if( provider ){
-
-			if( !na_updater_is_item_writable( updater, item, &reason )){
-				ret = ( guint ) reason;
-
-			} else {
-				ret = na_io_provider_delete_item( provider, item, messages );
-			}
+		g_return_val_if_fail( provider, ret );
 
-		} else {
-			ret = NA_IIO_PROVIDER_CODE_OK;
-		}
+		ret = na_io_provider_delete_item( provider, item, messages );
 	}
 
 	return( ret );
diff --git a/src/core/na-updater.h b/src/core/na-updater.h
index b61b6db..cd0e662 100644
--- a/src/core/na-updater.h
+++ b/src/core/na-updater.h
@@ -80,7 +80,7 @@ void       na_updater_remove_item( NAUpdater *updater, NAObject *item );
 
 /* read from / write to the physical storage subsystem
  */
-gboolean   na_updater_is_item_writable( const NAUpdater *updater, const NAObjectItem *item, gint *reason );
+gboolean   na_updater_is_item_writable( const NAUpdater *updater, const NAObjectItem *item, guint *reason );
 guint      na_updater_write_item      ( const NAUpdater *updater, NAObjectItem *item, GSList **messages );
 guint      na_updater_delete_item     ( const NAUpdater *updater, const NAObjectItem *item, GSList **messages );
 
diff --git a/src/nact/nact-main-menubar-edit.c b/src/nact/nact-main-menubar-edit.c
index 3111baf..76fc766 100644
--- a/src/nact/nact-main-menubar-edit.c
+++ b/src/nact/nact-main-menubar-edit.c
@@ -509,7 +509,7 @@ get_deletables( NAUpdater *updater, GList *selected, GSList **non_deletables )
 	GList *it;
 	GList *subitems;
 	GSList *sub_deletables;
-	gint reason;
+	guint reason;
 
 	to_delete = NULL;
 	for( it = selected ; it ; it = it->next ){
@@ -542,7 +542,7 @@ get_deletables_rec( NAUpdater *updater, GList *tree )
 	GSList *msgs;
 	GList *it;
 	GList *subitems;
-	gint reason;
+	guint reason;
 
 	msgs = NULL;
 	for( it = tree ; it ; it = it->next ){
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index 413555d..db0c161 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -94,7 +94,7 @@ struct _NactMainWindowPrivate {
 	 */
 	NAObjectItem    *selected_item;
 	gboolean         editable;
-	gint             reason;
+	guint            reason;
 
 	/**
 	 * Currently selected profile.



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