[nautilus-actions] Refactoring: rename src/core/na-object-class.h to src/api/na-object.h



commit 00544caabd02671ed3647f90ad0abbef768ae6d7
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Feb 15 17:37:38 2010 +0100

    Refactoring: rename src/core/na-object-class.h to src/api/na-object.h

 ChangeLog                                       |    1 +
 src/api/Makefile.am                             |    3 +-
 src/{core/na-object-class.h => api/na-object.h} |   83 +--
 src/core/Makefile.am                            |    1 +
 src/core/na-object.c                            |  859 +++++++----------------
 5 files changed, 293 insertions(+), 654 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a64a30f..0f2fe9d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
 2009-02-15 Pierre Wieser <pwieser trychlos org>
 
+	Rename src/core/na-object-class.h to src/api/na-object.h
 	Rename src/core/na-iduplicable.h to src/api/na-iduplicable.h
 	Rename src/core/na-gconf-utils.h to src/api/na-gconf-utils.h
 	Rename src/api/na-iio-provider.c to src/core/na-iio-provider.c
diff --git a/src/api/Makefile.am b/src/api/Makefile.am
index 361c9ed..ddc341b 100644
--- a/src/api/Makefile.am
+++ b/src/api/Makefile.am
@@ -38,6 +38,7 @@ api_include_HEADERS = \
 	na-gconf-monitor.h									\
 	na-gconf-utils.h									\
 	na-iduplicable.h									\
-	na-gconf-keys.h										\
 	na-object-api.h										\
+	na-object.h											\
+	na-gconf-keys.h										\
 	$(NULL)
diff --git a/src/core/na-object-class.h b/src/api/na-object.h
similarity index 67%
rename from src/core/na-object-class.h
rename to src/api/na-object.h
index e9eba3f..ebf2185 100644
--- a/src/core/na-object-class.h
+++ b/src/api/na-object.h
@@ -28,35 +28,29 @@
  *   ... and many others (see AUTHORS)
  */
 
-#ifndef __NAUTILUS_ACTIONS_NA_PRIVATE_OBJECT_CLASS_H__
-#define __NAUTILUS_ACTIONS_NA_PRIVATE_OBJECT_CLASS_H__
+#ifndef __NAUTILUS_ACTIONS_API_NA_OBJECT_H__
+#define __NAUTILUS_ACTIONS_API_NA_OBJECT_H__
 
 /**
  * SECTION: na_object
  * @short_description: #NAObject class definition.
- * @include: nautilus-actions/private/na-object-class.h
+ * @include: nautilus-actions/na-object.h
  *
- * This is the base class for managed objects.
- *
- * It implements the #NAIDuplicable interface in order to have easily
- * duplicable derived objects. All the public API of the interface is
- * converted to #NAObject virtual functions.
- *
- * The #NAObject class is a pure virtual class.
+ * This is the base class of all our data object hierarchy.
  */
 
 #include <glib-object.h>
 
 G_BEGIN_DECLS
 
-#define NA_OBJECT_TYPE					( na_object_get_type())
+#define NA_OBJECT_TYPE					( na_object_object_get_type())
 #define NA_OBJECT( object )				( G_TYPE_CHECK_INSTANCE_CAST( object, NA_OBJECT_TYPE, NAObject ))
 #define NA_OBJECT_CLASS( klass )		( G_TYPE_CHECK_CLASS_CAST( klass, NA_OBJECT_TYPE, NAObjectClass ))
 #define NA_IS_OBJECT( object )			( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_OBJECT_TYPE ))
 #define NA_IS_OBJECT_CLASS( klass )		( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_OBJECT_TYPE ))
 #define NA_OBJECT_GET_CLASS( object )	( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_OBJECT_TYPE, NAObjectClass ))
 
-typedef struct NAObjectPrivate NAObjectPrivate;
+typedef struct NAObjectPrivate      NAObjectPrivate;
 
 typedef struct {
 	GObject          parent;
@@ -81,22 +75,7 @@ typedef struct {
 	 * derived one. Each derived class has so only to take care of
 	 * dumping its own data.
 	 */
-	void       ( *dump )            ( const NAObject *object );
-
-	/**
-	 * new:
-	 * @object: a #NAObject-derived object of the class that we want
-	 * be returned.
-	 *
-	 * Returns: a newly allocated #NAObject of the same class that
-	 * @object.
-	 *
-	 * This is a pure virtual function: the most derived class should
-	 * implement it. #NAObject class defaults to return the object
-	 * allocated by the most derived class which implement this
-	 * function.
-	 */
-	NAObject * ( *new )             ( const NAObject *object );
+	void     ( *dump )     ( const NAObject *object );
 
 	/**
 	 * copy:
@@ -111,7 +90,7 @@ typedef struct {
 	 * base class up to the most-derived one. Each class has so only to
 	 * take care of dumping its own data.
 	 */
-	void       ( *copy )            ( NAObject *target, const NAObject *source );
+	void     ( *copy )     ( NAObject *target, const NAObject *source );
 
 	/**
 	 * are_equal:
@@ -130,7 +109,7 @@ typedef struct {
 	 * As soon as a difference is detected, the calling sequence will
 	 * be stopped, and the result returned.
 	 */
-	gboolean   ( *are_equal )       ( const NAObject *a, const NAObject *b );
+	gboolean ( *are_equal )( const NAObject *a, const NAObject *b );
 
 	/**
 	 * is_valid:
@@ -150,40 +129,24 @@ typedef struct {
 	 * As soon as a difference is detected, the calling sequence will
 	 * be stopped, and the result returned.
 	 */
-	gboolean   ( *is_valid )        ( const NAObject *object );
+	gboolean ( *is_valid ) ( const NAObject *object );
+}
+	NAObjectClass;
 
-	/**
-	 * get_childs:
-	 * @object: the #NAObject object whose childs are to be retrieved.
-	 *
-	 * Returns: a list of childs of @object, or NULL.
-	 *
-	 * As the returned list will not be freed by the caller, the
-	 * implementation should really returns its own list of childs,
-	 * if any.
-	 */
-	GList *    ( *get_childs )      ( const NAObject *object );
+GType  na_object_object_get_type( void );
 
-	/**
-	 * ref:
-	 * @object: the #NAObject object.
-	 *
-	 * Recursively ref the @object and all its childs.
-	 */
-	void       ( *ref )             ( NAObject *object );
+void   na_object_object_check_status( const NAObject *object );
 
-	/**
-	 * unref:
-	 * @object: the #NAObject object.
-	 *
-	 * Recursively unref the @object and all its childs.
-	 */
-	void       ( *unref )           ( NAObject *object );
-}
-	NAObjectClass;
+void   na_object_object_unref( NAObject *object );
+
+void   na_object_object_dump      ( const NAObject *object );
+void   na_object_object_dump_norec( const NAObject *object );
+void   na_object_object_dump_tree ( GList *tree );
 
-GType     na_object_get_type( void );
+#if 0
+GList *na_object_object_get_hierarchy( const NAObject *object );
+#endif
 
 G_END_DECLS
 
-#endif /* __NAUTILUS_ACTIONS_NA_PRIVATE_OBJECT_CLASS_H__ */
+#endif /* __NAUTILUS_ACTIONS_API_NA_OBJECT_H__ */
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 568633d..de947d5 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -42,6 +42,7 @@ libna_core_la_SOURCES = \
 	na-gconf-utils.c									\
 	na-iduplicable.c									\
 	na-iio-provider.c									\
+	na-object.c											\
 	\
 	na-iabout.c											\
 	na-iabout.h											\
diff --git a/src/core/na-object.c b/src/core/na-object.c
index 0185402..3c3ce68 100644
--- a/src/core/na-object.c
+++ b/src/core/na-object.c
@@ -32,12 +32,9 @@
 #include <config.h>
 #endif
 
-#include <string.h>
-
 #include <api/na-object-api.h>
 
-#include "na-iduplicable.h"
-#include "na-object-priv.h"
+#include "na-data-factory.h"
 
 /* private class data
  */
@@ -45,46 +42,55 @@ struct NAObjectClassPrivate {
 	void *empty;						/* so that gcc -pedantic is happy */
 };
 
-static GObjectClass *st_parent_class = NULL;
+/* private instance data
+ */
+struct NAObjectPrivate {
+	gboolean   dispose_has_run;
+};
+
+/* a structure to iter on the class hierarchy
+ */
+typedef struct {
+	NAObject *object;
+	gboolean  result;
+}
+	HierarchyIter;
+
+typedef gboolean ( *HierarchyIterFunc )( GObjectClass *class, const NAObject *object, void *user_data );
+
+static GObjectClass *st_parent_class   = NULL;
 
 static GType          register_type( void );
 static void           class_init( NAObjectClass *klass );
-static void           iduplicable_iface_init( NAIDuplicableInterface *iface );
 static void           instance_init( GTypeInstance *instance, gpointer klass );
-static void           instance_constructed( GObject *object );
 static void           instance_dispose( GObject *object );
 static void           instance_finalize( GObject *object );
 
-static NAIDuplicable *iduplicable_new( const NAIDuplicable *object );
+static void           iduplicable_iface_init( NAIDuplicableInterface *iface );
 static void           iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source );
+static gboolean       iduplicable_copy_iter( GObjectClass *class, const NAObject *target, NAObject *source );
 static gboolean       iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b );
+static gboolean       iduplicable_are_equal_iter( GObjectClass *class, const NAObject *a, HierarchyIter *str );
 static gboolean       iduplicable_is_valid( const NAIDuplicable *object );
+static gboolean       iduplicable_is_valid_iter( GObjectClass *class, const NAObject *a, HierarchyIter *str );
 
-static GList         *v_get_childs( const NAObject *object );
-static void           v_ref( NAObject *object );
-static void           v_unref( NAObject *object );
-
-static gboolean       are_equal_hierarchy( const NAObject *a, const NAObject *b );
-static void           copy_hierarchy( NAObject *target, const NAObject *source );
-static gboolean       do_are_equal( const NAObject *a, const NAObject *b );
-static void           do_copy( NAObject *target, const NAObject *source );
-static void           do_dump( const NAObject *object );
-static gboolean       do_is_valid( const NAObject *object );
-static void           dump_hierarchy( const NAObject *object );
+static void           object_dump( const NAObject *object );
+
+static gboolean       dump_class_hierarchy_iter( GObjectClass *class, const NAObject *object, void *user_data );
 static void           dump_tree( GList *tree, gint level );
-static gboolean       is_valid_hierarchy( const NAObject *object );
-static NAObject      *most_derived_new( const NAObject *object );
+static void           iter_on_class_hierarchy( const NAObject *object, HierarchyIterFunc pfn, void *user_data );
+static GList         *build_class_hierarchy( const NAObject *object );
 
 GType
-na_object_get_type( void )
+na_object_object_get_type( void )
 {
-	static GType object_type = 0;
+	static GType item_type = 0;
 
-	if( !object_type ){
-		object_type = register_type();
+	if( item_type == 0 ){
+		item_type = register_type();
 	}
 
-	return( object_type );
+	return( item_type );
 }
 
 static GType
@@ -95,8 +101,8 @@ register_type( void )
 
 	static GTypeInfo info = {
 		sizeof( NAObjectClass ),
-		( GBaseInitFunc ) NULL,
-		( GBaseFinalizeFunc ) NULL,
+		NULL,
+		NULL,
 		( GClassInitFunc ) class_init,
 		NULL,
 		NULL,
@@ -131,33 +137,12 @@ class_init( NAObjectClass *klass )
 	st_parent_class = g_type_class_peek_parent( klass );
 
 	object_class = G_OBJECT_CLASS( klass );
-	object_class->constructed = instance_constructed;
 	object_class->dispose = instance_dispose;
 	object_class->finalize = instance_finalize;
 
 	klass->private = g_new0( NAObjectClassPrivate, 1 );
 
-	klass->dump = do_dump;
-	klass->new = NULL;
-	klass->copy = do_copy;
-	klass->are_equal = do_are_equal;
-	klass->is_valid = do_is_valid;
-	klass->get_childs = NULL;
-	klass->ref = NULL;
-	klass->unref = NULL;
-}
-
-static void
-iduplicable_iface_init( NAIDuplicableInterface *iface )
-{
-	static const gchar *thisfn = "na_object_iduplicable_iface_init";
-
-	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
-	iface->new = iduplicable_new;
-	iface->copy = iduplicable_copy;
-	iface->are_equal = iduplicable_are_equal;
-	iface->is_valid = iduplicable_is_valid;
+	klass->dump = object_dump;
 }
 
 static void
@@ -167,29 +152,13 @@ instance_init( GTypeInstance *instance, gpointer klass )
 	NAObject *self;
 
 	g_debug( "%s: instance=%p (%s), klass=%p",
-			thisfn, ( void * ) instance, G_OBJECT_CLASS_NAME( klass ), ( void * ) klass );
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
+
 	g_return_if_fail( NA_IS_OBJECT( instance ));
+
 	self = NA_OBJECT( instance );
 
 	self->private = g_new0( NAObjectPrivate, 1 );
-
-	self->private->dispose_has_run = FALSE;
-}
-
-static void
-instance_constructed( GObject *object )
-{
-	/*static const gchar *thisfn = "na_object_instance_constructed";*/
-
-	/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
-	g_return_if_fail( NA_IS_OBJECT( object ));
-
-	na_iduplicable_init( NA_IDUPLICABLE( object ));
-
-	/* chain call to parent class */
-	if( G_OBJECT_CLASS( st_parent_class )->constructed ){
-		G_OBJECT_CLASS( st_parent_class )->constructed( object );
-	}
 }
 
 static void
@@ -199,15 +168,17 @@ instance_dispose( GObject *object )
 	NAObject *self;
 
 	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+
 	g_return_if_fail( NA_IS_OBJECT( object ));
+
 	self = NA_OBJECT( object );
 
 	if( !self->private->dispose_has_run ){
 
-		na_iduplicable_dispose( NA_IDUPLICABLE( object ));
-
 		self->private->dispose_has_run = TRUE;
 
+		na_iduplicable_dispose( NA_IDUPLICABLE( object ));
+
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
 			G_OBJECT_CLASS( st_parent_class )->dispose( object );
@@ -221,6 +192,7 @@ instance_finalize( GObject *object )
 	NAObject *self;
 
 	g_return_if_fail( NA_IS_OBJECT( object ));
+
 	self = NA_OBJECT( object );
 
 	g_free( self->private );
@@ -231,228 +203,187 @@ instance_finalize( GObject *object )
 	}
 }
 
-/**
- * na_object_iduplicable_check_status:
- * @object: the #NAObject object to be checked.
- *
- * Recursively checks for the edition status of @object and its childs
- * (if any).
- *
- * Internally set some properties which may be requested later. This
- * two-steps check-request let us optimize some work in the UI.
- *
- * na_object_check_status( object )
- *  +- na_iduplicable_check_status( object )
- *      +- get_origin( object )
- *      +- modified_status = v_are_equal( origin, object ) -> interface are_equal()
- *      +- valid_status = v_is_valid( object )             -> interface is_valid()
- *
- * Note that the recursivity is managed here, so that we can be sure
- * that edition status of childs is actually checked before those of
- * the parent.
- */
-void
-na_object_iduplicable_check_status( const NAObject *object )
+static void
+iduplicable_iface_init( NAIDuplicableInterface *iface )
 {
-	GList *childs, *ic;
+	static const gchar *thisfn = "na_object_iduplicable_iface_init";
 
-#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-	g_debug( "na_object_iduplicable_check_status: object=%p (%s)",
-			( void * ) object, G_OBJECT_TYPE_NAME( object ));
-#endif
-	g_return_if_fail( NA_IS_OBJECT( object ));
+	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
 
-	if( !object->private->dispose_has_run ){
+	iface->copy = iduplicable_copy;
+	iface->are_equal = iduplicable_are_equal;
+	iface->is_valid = iduplicable_is_valid;
+}
+
+static void
+iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
+{
+	g_return_if_fail( NA_IS_OBJECT( target ));
+	g_return_if_fail( NA_IS_OBJECT( source ));
+
+	if( !NA_OBJECT( source )->private->dispose_has_run &&
+		!NA_OBJECT( target )->private->dispose_has_run ){
 
-		childs = v_get_childs( object );
-		for( ic = childs ; ic ; ic = ic->next ){
-			na_object_iduplicable_check_status( NA_OBJECT( ic->data ));
+		if( NA_IS_IDATA_FACTORY( source )){
+			na_data_factory_copy( NA_IDATA_FACTORY( target ), NA_IDATA_FACTORY( source ));
+
+		} else {
+			iter_on_class_hierarchy( NA_OBJECT( source ),
+					( HierarchyIterFunc ) &iduplicable_copy_iter, ( void * ) target );
 		}
+	}
+}
 
-		na_iduplicable_check_status( NA_IDUPLICABLE( object ));
+static gboolean
+iduplicable_copy_iter( GObjectClass *class, const NAObject *source, NAObject *target )
+{
+	gboolean stop = FALSE;
+
+	if( NA_OBJECT_CLASS( class )->copy ){
+		NA_OBJECT_CLASS( class )->copy( target, source );
 	}
+
+	return( stop );
 }
 
-/**
- * na_object_iduplicable_duplicate:
- * @object: the #NAObject object to be dumped.
- *
- * Exactly duplicates a #NAObject-derived object.
- *
- * Returns: the new #NAObject.
- *
- *   na_object_duplicate( origin )
- *   +- na_object_iduplicable_duplicate( origin )
- *      +- na_iduplicable_duplicate( origin )
- *         +- dup = v_new( object )
- *         |  +- interface->new( object)
- *         |     +- iduplicable_new( object )
- *         |        +- most_derived_new( object )
- *         |           +- object_new( ... ) from a derived class
- *         +- v_copy( dup, origin )
- *         |  +- interface->copy( dup, origin )
- *         |     +- iduplicable_copy( target, source )
- *         |        +- copy_hierarchy( target, source )
- *         |           +- object_copy( ... ) from each successive derived class
- *         +- set_origin( dup, origin )
- *         +- set_modified( dup, FALSE )
- *         +- set_valid( dup, FALSE )
- *
- * Though the interface api is not recursive per se, the implementation
- * is ; i.e. duplicating a #NAObjectItem also duplicates the whole tree
- * inside.
- */
-NAObject *
-na_object_iduplicable_duplicate( const NAObject *object )
+static gboolean
+iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
 {
-	NAIDuplicable *duplicate = NULL;
+	gboolean are_equal;
+	HierarchyIter *str;
 
-	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
-	g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
+	g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
+	g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
 
-	if( !object->private->dispose_has_run ){
+	are_equal = FALSE;
+
+	if( !NA_OBJECT( a )->private->dispose_has_run &&
+		!NA_OBJECT( b )->private->dispose_has_run ){
+
+		if( NA_IS_IDATA_FACTORY( a )){
+			are_equal = na_data_factory_are_equal( NA_IDATA_FACTORY( a ), NA_IDATA_FACTORY( b ));
 
-		duplicate = na_iduplicable_duplicate( NA_IDUPLICABLE( object ));
+		} else {
+			str = g_new0( HierarchyIter, 1 );
+			str->object = NA_OBJECT( b );
+			str->result = FALSE;
 
-		/*g_debug( "na_object_iduplicable_duplicate: object=%p (%s), duplicate=%p (%s)",
-				( void * ) object, G_OBJECT_TYPE_NAME( object ),
-				( void * ) duplicate, duplicate ? G_OBJECT_TYPE_NAME( duplicate ) : "" );*/
+			iter_on_class_hierarchy( NA_OBJECT( a ), ( HierarchyIterFunc ) &iduplicable_are_equal_iter, str );
+
+			are_equal = str->result;
+
+			g_free( str );
+		}
 	}
 
-	/* do not use NA_OBJECT macro as we may return a (valid) NULL value */
-	return(( NAObject * ) duplicate );
+	return( are_equal );
 }
 
-/**
- * na_object_iduplicable_get_origin:
- * @object: the #NAObject object whose status is requested.
- *
- * Returns the original object which was at the origin of @object.
- *
- * Returns: a #NAObject, or NULL.
- */
-NAObject *
-na_object_iduplicable_get_origin( const NAObject *object )
+static gboolean
+iduplicable_are_equal_iter( GObjectClass *class, const NAObject *a, HierarchyIter *str )
 {
-	NAObject *origin = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+	gboolean stop = FALSE;
 
-	if( !object->private->dispose_has_run ){
-		/* do not use NA_OBJECT macro as we may return a (valid) NULL value */
-		origin = ( NAObject * ) na_iduplicable_get_origin( NA_IDUPLICABLE( object ));
+	if( NA_OBJECT_CLASS( class )->are_equal ){
+		str->result = NA_OBJECT_CLASS( class )->are_equal( a, str->object );
+		stop = !str->result;
 	}
 
-	return( origin );
+	return( stop );
 }
 
-/**
- * na_object_iduplicable_set_origin:
- * @object: the #NAObject object whose origin is to be set.
- * @origin: a #NAObject which will be set as the new origin of @object.
- *
- * Sets the new origin of @object, and of all its childs.
- *
- * Be warned: but recursively reinitializing the origin to NULL, this
- * function may cause difficult to solve issues.
- */
-void
-na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin )
+static gboolean
+iduplicable_is_valid( const NAIDuplicable *object )
 {
-	GList *childs, *ic;
+	gboolean is_valid = FALSE;
+	HierarchyIter *str;
 
-	g_return_if_fail( NA_IS_OBJECT( object ));
-	g_return_if_fail( NA_IS_OBJECT( origin ) || !origin );
+	if( !NA_OBJECT( object )->private->dispose_has_run ){
 
-	if( !object->private->dispose_has_run &&
-		( !origin || !origin->private->dispose_has_run )){
+		str = g_new0( HierarchyIter, 1 );
 
-			na_iduplicable_set_origin( NA_IDUPLICABLE( object ), NA_IDUPLICABLE( origin ));
+		iter_on_class_hierarchy( NA_OBJECT( object ), ( HierarchyIterFunc ) &iduplicable_is_valid_iter, str );
 
-			childs = v_get_childs( object );
-			for( ic = childs ; ic ; ic = ic->next ){
-				na_object_iduplicable_set_origin( NA_OBJECT( ic->data ), origin );
-			}
+		is_valid = str->result;
+
+		g_free( str );
 	}
+
+	return( is_valid );
 }
 
-/**
- * na_object_iduplicable_are_equal:
- * @a: a first #NAObject object.
- * @b: a second #NAObject object to be compared to the first one.
- *
- * Compares the two #NAObject objects.
- *
- * At least when it finds that @a and @b are equal, each derived
- * class should call its parent class to give it an opportunity to
- * detect a difference.
- *
- * Returns: %TRUE if @a and @b are identical, %FALSE else.
- */
-gboolean
-na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b )
+static gboolean
+iduplicable_is_valid_iter( GObjectClass *class, const NAObject *a, HierarchyIter *str )
 {
-	gboolean are_equal = FALSE;
-
-	g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
-	g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
+	gboolean stop = FALSE;
 
-	if( !a->private->dispose_has_run && !b->private->dispose_has_run ){
-		are_equal = are_equal_hierarchy( a, b );
+	if( NA_OBJECT_CLASS( class )->is_valid ){
+		str->result = NA_OBJECT_CLASS( class )->is_valid( a );
+		stop = !str->result;
 	}
 
-	return( are_equal );
+	return( stop );
 }
 
-/**
- * na_object_iduplicable_is_modified:
- * @object: the #NAObject object whose status is requested.
- *
- * Returns the current modification status of @object.
- *
- * This suppose that @object has been previously duplicated in order
- * to get benefits provided by the IDuplicable interface.
- *
- * This suppose also that the edition status of @object has previously
- * been checked via na_object_check_status().
- *
- * Returns: %TRUE is the provided object has been modified regarding to
- * the original one, %FALSE else.
- */
-gboolean
-na_object_iduplicable_is_modified( const NAObject *object )
+static void
+object_dump( const NAObject *object )
 {
-	gboolean is_modified = FALSE;
+	static const char *thisfn = "na_object_do_dump";
 
-	g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+	g_debug( "%s: object=%p (%s, ref_count=%d)", thisfn,
+			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
 
-	if( !object->private->dispose_has_run ){
-		is_modified = na_iduplicable_is_modified( NA_IDUPLICABLE( object ));
-	}
+	na_iduplicable_dump( NA_IDUPLICABLE( object ));
 
-	return( is_modified );
+	if( NA_IS_IDATA_FACTORY( object )){
+		na_data_factory_dump( NA_IDATA_FACTORY( object ));
+	}
 }
 
 /**
- * na_object_iduplicable_is_valid:
- * @object: the #NAObject object whose validity is to be checked.
+ * na_object_object_check_status:
+ * @object: the #NAObject-derived object to be checked.
  *
- * Gets the validity status of @object.
+ * Recursively checks for the edition status of @object and its childs
+ * (if any).
+ *
+ * Internally set some properties which may be requested later. This
+ * two-steps check-request let us optimize some work in the UI.
+ *
+ * na_object_editable_check_status( object )
+ *  +- na_iduplicable_check_status( object )
+ *      +- get_origin( object )
+ *      +- modified_status = v_are_equal( origin, object ) -> interface are_equal()
+ *      +- valid_status = v_is_valid( object )             -> interface is_valid()
  *
- * Returns: %TRUE is @object is valid, %FALSE else.
+ * Note that the recursivity is managed here, so that we can be sure
+ * that edition status of childs is actually checked before those of
+ * the parent.
  */
-gboolean
-na_object_iduplicable_is_valid( const NAObject *object )
+void
+na_object_object_check_status( const NAObject *object )
 {
-	gboolean is_valid = FALSE;
+	static const gchar *thisfn = "na_object_object_check_status";
+	GList *childs, *ic;
+
+	g_debug( "%s: object=%p (%s)",
+			thisfn,
+			( void * ) object, G_OBJECT_TYPE_NAME( object ));
 
-	g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+	g_return_if_fail( NA_IS_OBJECT( object ));
 
 	if( !object->private->dispose_has_run ){
-		is_valid = na_iduplicable_is_valid( NA_IDUPLICABLE( object ));
-	}
 
-	return( is_valid );
+		if( NA_IS_OBJECT_ITEM( object )){
+
+			childs = na_object_get_items( object );
+			for( ic = childs ; ic ; ic = ic->next ){
+				na_object_check_status( ic->data );
+			}
+		}
+
+		na_iduplicable_check_status( NA_IDUPLICABLE( object ));
+	}
 }
 
 /**
@@ -477,11 +408,15 @@ na_object_object_dump( const NAObject *object )
 
 	if( !object->private->dispose_has_run ){
 
-		na_object_object_dump_norec( object );
+		na_object_dump_norec( object );
+
+		if( NA_IS_OBJECT_ITEM( object )){
 
-		childs = v_get_childs( object );
-		for( ic = childs ; ic ; ic = ic->next ){
-			na_object_object_dump( NA_OBJECT( ic->data ));
+			childs = na_object_get_items( object );
+			for( ic = childs ; ic ; ic = ic->next ){
+
+				na_object_dump( ic->data );
+			}
 		}
 	}
 }
@@ -500,168 +435,64 @@ na_object_object_dump_norec( const NAObject *object )
 	g_return_if_fail( NA_IS_OBJECT( object ));
 
 	if( !object->private->dispose_has_run ){
-		dump_hierarchy( object );
-	}
-}
-
-/**
- * na_object_object_dump_tree:
- * @tree: a hierarchical list of #NAObject-derived objects.
- *
- * Outputs a brief, hierarchical dump of the provided list.
- */
-void
-na_object_object_dump_tree( GList *tree )
-{
-	dump_tree( tree, 0 );
-}
-
-/**
- * na_object_object_ref:
- * @object: a #NAObject-derived object.
- *
- * Recursively ref the @object and all its childs, incrementing their
- * reference_count by 1.
- *
- * Returns: a reference on the @pbject.
- */
-NAObject *
-na_object_object_ref( NAObject *object )
-{
-	NAObject *ref = NULL;
-
-	g_debug( "na_object_object_ref: object=%p (%s, ref_count=%d)",
-			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
-	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
-
-	if( !object->private->dispose_has_run ){
-
-		v_ref( object );
 
-		ref = g_object_ref( object );
+		iter_on_class_hierarchy( object, ( HierarchyIterFunc ) &dump_class_hierarchy_iter, NULL );
 	}
-
-	return( ref );
 }
 
-/**
- * na_object_object_reset_origin:
- * @object: a #NAObject-derived object.
- * @origin: must be a duplication of @object.
- *
- * Recursively reset origin of @object and its childs to @origin and
- * its childs), so that @origin appear as the actual origin of @object.
- *
- * The origin of @origin itself is set to NULL.
- *
- * This only works if @origin has just been duplicated from @object,
- * and thus we do not have to check if childs lists are equal.
- */
-void
-na_object_object_reset_origin( NAObject *object, const NAObject *origin )
+static gboolean
+dump_class_hierarchy_iter( GObjectClass *class, const NAObject *object, void *user_data )
 {
-	GList *origin_childs, *iorig;
-	GList *object_childs, *iobj;
-	NAObject *orig_object;
-
-	g_return_if_fail( NA_IS_OBJECT( origin ));
-	g_return_if_fail( NA_IS_OBJECT( object ));
-
-	if( !object->private->dispose_has_run && !origin->private->dispose_has_run ){
+	gboolean stop = FALSE;
 
-		origin_childs = v_get_childs( origin );
-		object_childs = v_get_childs( object );
-		for( iorig = origin_childs, iobj = object_childs ; iorig && iobj ; iorig = iorig->next, iobj = iobj->next ){
-			orig_object = na_object_get_origin( iorig->data );
-			g_return_if_fail( orig_object == iobj->data );
-			na_object_reset_origin( iobj->data, iorig->data );
-		}
-
-		orig_object = na_object_get_origin( origin );
-		g_return_if_fail( orig_object == object );
-		na_iduplicable_set_origin( NA_IDUPLICABLE( object ), NA_IDUPLICABLE( origin ));
-		na_iduplicable_set_origin( NA_IDUPLICABLE( origin ), NULL );
+	if( NA_OBJECT_CLASS( class )->dump ){
+		NA_OBJECT_CLASS( class )->dump( object );
 	}
+
+	return( stop );
 }
 
 /**
- * na_object_object_reset_status:
- * @object: a #NAObject-derived object.
- *
- * Recursively reset status of @object and its childs.
+ * na_object_object_dump_tree:
+ * @tree: a hierarchical list of #NAObject-derived objects.
  *
- * This is typically used when we want display a clean list of current
- * items (e.g. in Export assistant).
+ * Outputs a brief, hierarchical dump of the provided list.
  */
 void
-na_object_object_reset_status( NAObject *object )
+na_object_object_dump_tree( GList *tree )
 {
-	GList *object_childs, *iobj;
-
-	g_return_if_fail( NA_IS_OBJECT( object ));
-
-	if( !object->private->dispose_has_run ){
-
-		object_childs = v_get_childs( object );
-		for( iobj = object_childs ; iobj ; iobj = iobj->next ){
-			na_iduplicable_reset_status( NA_IDUPLICABLE( iobj->data ));
-		}
-
-		na_iduplicable_reset_status( NA_IDUPLICABLE( object ));
-	}
+	dump_tree( tree, 0 );
 }
 
-/**
- * na_object_object_unref:
- * @object: a #NAObject-derived object.
- *
- * Recursively unref the @object and all its childs, decrementing their
- * reference_count by 1.
- */
-void
-na_object_object_unref( NAObject *object )
+static void
+dump_tree( GList *tree, gint level )
 {
-	g_debug( "na_object_object_unref: object=%p (%s, ref_count=%d)",
-			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
-
-	g_return_if_fail( NA_IS_OBJECT( object ));
-
-	if( !object->private->dispose_has_run ){
-
-		v_unref( object );
+	GString *prefix;
+	gint i;
+	GList *subitems, *it;
+	gchar *id;
+	gchar *label;
 
-		g_object_unref( object );
+	prefix = g_string_new( "" );
+	for( i = 0 ; i < level ; ++i ){
+		g_string_append_printf( prefix, "  " );
 	}
-}
-
-/**
- * na_object_most_derived_get_childs:
- * @object: this #NAObject instance.
- *
- * Returns: the list of childs as returned by the most derived class
- * which implements the virtual function 'get_childs'.
- *
- * The returned list should be g_list_free() by the caller.
- */
-GList *
-na_object_most_derived_get_childs( const NAObject *object )
-{
-	GList *childs;
-	GList *hierarchy, *ih;
-	gboolean found;
 
-	found = FALSE;
-	childs = NULL;
-	hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
+	for( it = tree ; it ; it = it->next ){
+		id = na_object_get_id( it->data );
+		label = na_object_get_label( it->data );
+		g_debug( "na_object_dump_tree: %s%p (%s) %s \"%s\"",
+				prefix->str, ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ), id, label );
+		g_free( id );
+		g_free( label );
 
-	for( ih = hierarchy ; ih && !found ; ih = ih->next ){
-		if( NA_OBJECT_CLASS( ih->data )->get_childs ){
-			childs = NA_OBJECT_CLASS( ih->data )->get_childs( object );
-			found = TRUE;
+		if( NA_IS_OBJECT_ITEM( it->data )){
+			subitems = na_object_get_items( it->data );
+			dump_tree( subitems, level+1 );
 		}
 	}
 
-	return( childs );
+	g_string_free( prefix, TRUE );
 }
 
 /**
@@ -669,9 +500,12 @@ na_object_most_derived_get_childs( const NAObject *object )
  *
  * Returns the class hierarchy,
  * from the topmost base class, to the most-derived one.
+ *
+ * The returned list should be released with g_list_free() by the caller.
  */
+#if 0
 GList *
-na_object_get_hierarchy( const NAObject *object )
+na_object_object_get_hierarchy( const NAObject *object )
 {
 	GList *hierarchy = NULL;
 	GObjectClass *class;
@@ -683,6 +517,7 @@ na_object_get_hierarchy( const NAObject *object )
 		class = G_OBJECT_GET_CLASS( object );
 
 		while( G_OBJECT_CLASS_TYPE( class ) != NA_OBJECT_TYPE ){
+
 			hierarchy = g_list_prepend( hierarchy, class );
 			class = g_type_class_peek_parent( class );
 		}
@@ -692,246 +527,84 @@ na_object_get_hierarchy( const NAObject *object )
 
 	return( hierarchy );
 }
+#endif
 
 /**
- * na_object_free_hierarchy:
+ * na_object_object_unref:
+ * @object: a #NAObject-derived object.
+ *
+ * Recursively unref the @object and all its childs, decrementing their
+ * reference_count by 1.
  */
 void
-na_object_free_hierarchy( GList *hierarchy )
-{
-	g_list_free( hierarchy );
-}
-
-static NAIDuplicable *
-iduplicable_new( const NAIDuplicable *object )
-{
-	NAIDuplicable *new_object = NULL;
-
-	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
-
-	if( !NA_OBJECT( object )->private->dispose_has_run ){
-		/* do not use NA_IDUPLICABLE macro as we may return a (valid) NULL value */
-		new_object = ( NAIDuplicable * ) most_derived_new( NA_OBJECT( object ));
-	}
-
-	return( new_object );
-}
-
-static void
-iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
-{
-	g_return_if_fail( NA_IS_OBJECT( target ));
-	g_return_if_fail( NA_IS_OBJECT( source ));
-
-	if( !NA_OBJECT( source )->private->dispose_has_run &&
-		!NA_OBJECT( target )->private->dispose_has_run ){
-
-			copy_hierarchy( NA_OBJECT( target ), NA_OBJECT( source ));
-	}
-}
-
-static gboolean
-iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
-{
-	gboolean are_equal = FALSE;
-
-	g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
-	g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
-
-	if( !NA_OBJECT( a )->private->dispose_has_run &&
-		!NA_OBJECT( b )->private->dispose_has_run ){
-
-		are_equal = are_equal_hierarchy( NA_OBJECT( a ), NA_OBJECT( b ));
-	}
-
-	return( are_equal );
-}
-
-static gboolean
-iduplicable_is_valid( const NAIDuplicable *object )
+na_object_object_unref( NAObject *object )
 {
-	gboolean is_valid = FALSE;
-
-	if( !NA_OBJECT( object )->private->dispose_has_run ){
-		is_valid = is_valid_hierarchy( NA_OBJECT( object ));
-	}
-
-	return( is_valid );
-}
-
-static GList *
-v_get_childs( const NAObject *object ){
+	GList *childs, *ic;
 
-	return( na_object_most_derived_get_childs( object ));
-}
+	g_debug( "na_object_object_unref: object=%p (%s, ref_count=%d)",
+			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
 
-static void
-v_ref( NAObject *object )
-{
-	if( NA_OBJECT_GET_CLASS( object )->ref ){
-		NA_OBJECT_GET_CLASS( object )->ref( object );
-	}
-}
+	g_return_if_fail( NA_IS_OBJECT( object ));
 
-static void
-v_unref( NAObject *object )
-{
-	if( NA_OBJECT_GET_CLASS( object )->unref ){
-		NA_OBJECT_GET_CLASS( object )->unref( object );
-	}
-}
+	if( !object->private->dispose_has_run ){
 
-static gboolean
-are_equal_hierarchy( const NAObject *a, const NAObject *b )
-{
-	gboolean are_equal;
-	GList *hierarchy, *ih;
+		if( NA_IS_OBJECT_ITEM( object )){
 
-	are_equal = TRUE;
-	hierarchy = na_object_get_hierarchy( b );
+			childs = na_object_get_items( object );
+			for( ic = childs ; ic ; ic = ic->next ){
 
-	for( ih = hierarchy ; ih && are_equal ; ih = ih->next ){
-		if( NA_OBJECT_CLASS( ih->data )->are_equal ){
-			are_equal = NA_OBJECT_CLASS( ih->data )->are_equal( a, b );
+				na_object_unref( ic->data );
+			}
 		}
-	}
-
-	na_object_free_hierarchy( hierarchy );
 
-	return( are_equal );
-}
-
-static void
-copy_hierarchy( NAObject *target, const NAObject *source )
-{
-	GList *hierarchy, *ih;
-
-	hierarchy = na_object_get_hierarchy( source );
-
-	for( ih = hierarchy ; ih ; ih = ih->next ){
-		if( NA_OBJECT_CLASS( ih->data )->copy ){
-			NA_OBJECT_CLASS( ih->data )->copy( target, source );
-		}
+		g_object_unref( object );
 	}
-
-	na_object_free_hierarchy( hierarchy );
-}
-
-static gboolean
-do_are_equal( const NAObject *a, const NAObject *b )
-{
-	return( TRUE );
-}
-
-static void
-do_copy( NAObject *target, const NAObject *source )
-{
-	/* nothing to do here */
-}
-
-static void
-do_dump( const NAObject *object )
-{
-	static const char *thisfn = "na_object_do_dump";
-
-	g_debug( "%s: object=%p (%s, ref_count=%d)", thisfn,
-			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
-
-	na_iduplicable_dump( NA_IDUPLICABLE( object ));
-}
-
-static gboolean
-do_is_valid( const NAObject *object )
-{
-	return( TRUE );
 }
 
+/*
+ * iter on the whole class hierarchy
+ * starting with NAObject, and to the most derived up to NAObjectAction..
+ */
 static void
-dump_hierarchy( const NAObject *object )
+iter_on_class_hierarchy( const NAObject *object, HierarchyIterFunc pfn, void *user_data )
 {
+	gboolean stop;
+	GObjectClass *class;
 	GList *hierarchy, *ih;
 
-	hierarchy = na_object_get_hierarchy( object );
-
-	for( ih = hierarchy ; ih ; ih = ih->next ){
-		if( NA_OBJECT_CLASS( ih->data )->dump ){
-			NA_OBJECT_CLASS( ih->data )->dump( object );
-		}
-	}
-
-	na_object_free_hierarchy( hierarchy );
-}
-
-static void
-dump_tree( GList *tree, gint level )
-{
-	GString *prefix;
-	gint i;
-	GList *subitems, *it;
-	gchar *id;
-	gchar *label;
-
-	prefix = g_string_new( "" );
-	for( i = 0 ; i < level ; ++i ){
-		g_string_append_printf( prefix, "  " );
-	}
-
-	for( it = tree ; it ; it = it->next ){
-		id = na_object_get_id( it->data );
-		label = na_object_get_label( it->data );
-		g_debug( "na_object_dump_tree: %s%p (%s) %s \"%s\"",
-				prefix->str, ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ), id, label );
-		g_free( id );
-		g_free( label );
+	stop = FALSE;
+	hierarchy = build_class_hierarchy( object );
 
-		if( NA_IS_OBJECT_ITEM( it->data )){
-			subitems = na_object_get_items_list( it->data );
-			dump_tree( subitems, level+1 );
-		}
+	for( ih = hierarchy ; ih && !stop ; ih = ih->next ){
+		class = ( GObjectClass * ) ih->data;
+		/*g_debug( "iter_on_class_hierarchy: class=%s", G_OBJECT_CLASS_NAME( class ));*/
+		stop = ( *pfn )( class, object, user_data );
 	}
 
-	g_string_free( prefix, TRUE );
+	g_list_free( hierarchy );
 }
 
-static gboolean
-is_valid_hierarchy( const NAObject *object )
+/*
+ * build the class hierarchy
+ * returns a list of GObjectClass, which starts with NAObject,
+ * and to with the most derived class (e.g. NAObjectAction or so)
+ */
+static GList *
+build_class_hierarchy( const NAObject *object )
 {
-	gboolean is_valid;
-	GList *hierarchy, *ih;
-
-	is_valid = TRUE;
-	hierarchy = na_object_get_hierarchy( object );
-
-	for( ih = hierarchy ; ih && is_valid ; ih = ih->next ){
-		if( NA_OBJECT_CLASS( ih->data )->is_valid ){
-			is_valid = NA_OBJECT_CLASS( ih->data )->is_valid( object );
-		}
-	}
-
-	na_object_free_hierarchy( hierarchy );
-
-	return( is_valid );
-}
+	GObjectClass *class;
+	GList *hierarchy;
 
-static NAObject *
-most_derived_new( const NAObject *object )
-{
-	NAObject *new_object;
-	GList *hierarchy, *ih;
-	gboolean found;
+	hierarchy = NULL;
+	class = G_OBJECT_GET_CLASS( object );
 
-	found = FALSE;
-	new_object = NULL;
-	hierarchy = g_list_reverse( na_object_get_hierarchy( object ));
+	while( G_OBJECT_CLASS_TYPE( class ) != NA_OBJECT_TYPE ){
 
-	for( ih = hierarchy ; ih && !found ; ih = ih->next ){
-		if( NA_OBJECT_CLASS( ih->data )->new ){
-			new_object = NA_OBJECT_CLASS( ih->data )->new( object );
-			found = TRUE;
-		}
+		hierarchy = g_list_prepend( hierarchy, class );
+		class = g_type_class_peek_parent( class );
 	}
 
-	na_object_free_hierarchy( hierarchy );
+	hierarchy = g_list_prepend( hierarchy, class );
 
-	return( new_object );
+	return( hierarchy );
 }



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