[nautilus-actions] Fix display of modification status in NACT



commit b5de6a32fb18cd97f703f640bebb33f2e28ac5ad
Author: Pierre Wieser <pwieser trychlos org>
Date:   Fri Feb 26 11:08:12 2010 +0100

    Fix display of modification status in NACT

 ChangeLog                            |   34 +++++++++++++
 src/api/na-iduplicable.h             |    1 +
 src/api/na-object-api.h              |    2 +-
 src/api/na-object-item.h             |    1 +
 src/core/na-data-boxed.c             |    5 ++-
 src/core/na-factory-object.c         |   72 +++++++++++++---------------
 src/core/na-iduplicable.c            |   60 ++++++++++++++++++++---
 src/core/na-object-action-factory.c  |    2 +-
 src/core/na-object-action.c          |    2 +-
 src/core/na-object-item-factory.c    |    8 ++--
 src/core/na-object-item.c            |   88 ++++++++++++++++++++++++----------
 src/core/na-object-menu.c            |    2 +-
 src/core/na-object-profile-factory.c |    8 +--
 src/core/na-object-profile.c         |    4 +-
 src/core/na-object.c                 |   53 ++++++++++++++------
 src/core/na-pivot.c                  |    4 +-
 src/core/na-updater.c                |    2 +-
 src/nact/nact-iactions-list.c        |    1 +
 18 files changed, 244 insertions(+), 105 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index f1bfb37..b49457e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,39 @@
 2009-02-26 Pierre Wieser <pwieser trychlos org>
 
+	Fix display of modification status in NACT.
+
+	* src/api/na-iduplicable.h:
+	* src/core/na-iduplicable.c (na_iduplicable_set_modified):
+	New function.
+
+	* src/api/na-object-api.h:
+	* src/api/na-object-item.h:
+	* src/core/na-object-item.c (na_object_item_unref_items_rec):
+	New function.
+
+	* src/core/na-data-boxed.c (string_are_equal):
+	* src/core/na-factory-object.c (na_factory_object_are_equal):
+	* src/core/na-object.c (na_object_object_check_status_up):
+	Rewrite equality tests.
+
+	* src/core/na-object-action-factory.c:
+	* src/core/na-object-item-factory.c:
+	* src/core/na-object-profile-factory.c:
+	* src/core/na-object-action.c:
+	* src/core/na-object-menu.c:
+	* src/core/na-object-profile.c:
+	Review one more time default values and initial allocations.
+
+	* src/core/na-pivot.c (instance_dispose, na_pivot_load_items:
+	Only unref the first level of items.
+
+	* src/core/na-updater.c (na_updater_remove_item):
+	Only unref the removed object as it will take care of also unreffing
+	its children if its reference count is correct.
+
+	* src/nact/nact-iactions-list.c (display_label):
+	Add a commented debug line.
+
 	* src/test/check-po.sh: Test cpompleteness of po/POTFILES.in.
 	* src/test/time.sh: Bench the elapsed build time.
 
diff --git a/src/api/na-iduplicable.h b/src/api/na-iduplicable.h
index f37d4b1..dae82fd 100644
--- a/src/api/na-iduplicable.h
+++ b/src/api/na-iduplicable.h
@@ -140,6 +140,7 @@ gboolean       na_iduplicable_is_valid    ( const NAIDuplicable *object );
 gboolean       na_iduplicable_is_modified ( const NAIDuplicable *object );
 
 void           na_iduplicable_set_origin  ( NAIDuplicable *object, const NAIDuplicable *origin );
+void           na_iduplicable_set_modified( NAIDuplicable *object, gboolean is_modified );
 
 void           na_iduplicable_register_consumer( GObject *consumer );
 
diff --git a/src/api/na-object-api.h b/src/api/na-object-api.h
index b3b3043..1a3c7ec 100644
--- a/src/api/na-object-api.h
+++ b/src/api/na-object-api.h
@@ -122,7 +122,7 @@ G_BEGIN_DECLS
 
 #define na_object_get_items_count( obj )				na_object_item_get_items_count( NA_OBJECT_ITEM( obj ))
 #define na_object_count_items( list, cm, ca, cp, brec )	na_object_item_count_items( list, ( cm ), ( ca ), ( cp ), ( brec ))
-#define na_object_unref_items( tree )					na_object_item_unref_items( tree )
+#define na_object_unref_items( tree )					na_object_item_unref_items_rec( tree )
 
 /* NAObjectAction
  */
diff --git a/src/api/na-object-item.h b/src/api/na-object-item.h
index 3ce395e..99ab3fa 100644
--- a/src/api/na-object-item.h
+++ b/src/api/na-object-item.h
@@ -91,6 +91,7 @@ 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_unref_items( GList *items );
+void        na_object_item_unref_items_rec( GList *items );
 
 void        na_object_item_factory_write_start( NAObjectItem *item );
 
diff --git a/src/core/na-data-boxed.c b/src/core/na-data-boxed.c
index ccf60f5..bbc789e 100644
--- a/src/core/na-data-boxed.c
+++ b/src/core/na-data-boxed.c
@@ -831,7 +831,10 @@ string_are_equal( const NADataBoxed *a, const NADataBoxed *b )
 	if( !a->private->u.string || !b->private->u.string ){
 		return( FALSE );
 	}
-	return( strcmp( a->private->u.string, b->private->u.string ) == 0 );
+	if( strcmp( a->private->u.string, b->private->u.string ) == 0 ){
+		return( TRUE );
+	}
+	return( FALSE );
 }
 
 static gboolean
diff --git a/src/core/na-factory-object.c b/src/core/na-factory-object.c
index 81d1082..8661a66 100644
--- a/src/core/na-factory-object.c
+++ b/src/core/na-factory-object.c
@@ -380,30 +380,52 @@ na_factory_object_copy( NAIFactoryObject *target, const NAIFactoryObject *source
 gboolean
 na_factory_object_are_equal( const NAIFactoryObject *a, const NAIFactoryObject *b )
 {
+	static const gchar *thisfn = "na_factory_object_are_equal";
 	gboolean are_equal;
-	GList *a_list, *b_list, *ia;
+	GList *a_list, *b_list, *ia, *ib;
 
 	are_equal = FALSE;
 
 	a_list = g_object_get_data( G_OBJECT( a ), NA_IFACTORY_OBJECT_PROP_DATA );
 	b_list = g_object_get_data( G_OBJECT( b ), NA_IFACTORY_OBJECT_PROP_DATA );
 
-	if( g_list_length( a_list ) == g_list_length( b_list )){
+	are_equal = TRUE;
+	for( ia = a_list ; ia && are_equal ; ia = ia->next ){
+
+		NADataBoxed *a_boxed = NA_DATA_BOXED( ia->data );
+		NADataDef *a_def = na_data_boxed_get_data_def( a_boxed );
+		if( a_def->comparable ){
+
+			NADataBoxed *b_boxed = data_boxed_from_name( b, a_def->name );
+			if( b_boxed ){
+				are_equal = na_data_boxed_are_equal( a_boxed, b_boxed );
+				if( !are_equal ){
+					g_debug( "%s: %s not equal as %s different", thisfn, G_OBJECT_TYPE_NAME( a ), a_def->name );
+				}
 
-		are_equal = TRUE;
-		for( ia = a_list ; ia && are_equal ; ia = ia->next ){
+			} else {
+				are_equal = FALSE;
+				g_debug( "%s: %s not equal as %s not set", thisfn, G_OBJECT_TYPE_NAME( a ), a_def->name );
+			}
+		}
+	}
 
-			NADataBoxed *a_boxed = NA_DATA_BOXED( ia->data );
-			NADataDef *a_def = na_data_boxed_get_data_def( a_boxed );
-			if( a_def->comparable ){
+	for( ib = b_list ; ib && are_equal ; ib = ib->next ){
 
-				NADataBoxed *b_boxed = data_boxed_from_name( b, a_def->name );
-				if( b_boxed ){
-					are_equal = na_data_boxed_are_equal( a_boxed, b_boxed );
+		NADataBoxed *b_boxed = NA_DATA_BOXED( ib->data );
+		NADataDef *b_def = na_data_boxed_get_data_def( b_boxed );
+		if( b_def->comparable ){
 
-				} else {
-					are_equal = FALSE;
+			NADataBoxed *a_boxed = data_boxed_from_name( a, b_def->name );
+			if( a_boxed ){
+				are_equal = na_data_boxed_are_equal( a_boxed, b_boxed );
+				if( !are_equal ){
+					g_debug( "%s: %s not equal as %s different", thisfn, G_OBJECT_TYPE_NAME( a ), b_def->name );
 				}
+
+			} else {
+				are_equal = FALSE;
+				g_debug( "%s: %s not equal as %s not set", thisfn, G_OBJECT_TYPE_NAME( a ), b_def->name );
 			}
 		}
 	}
@@ -874,32 +896,6 @@ v_write_done( NAIFactoryObject *serializable, const NAIFactoryProvider *writer,
 	return( code );
 }
 
-#if 0
-/**
- * na_factory_object_set_from_string:
- * @object: this #NAIFactoryObject instance.
- * @property_id: the elementary data id.
- * @string: the string to be set in the element.
- *
- * Set the @object with the @string.
- */
-void
-na_factory_object_set_from_string( NAIFactoryObject *object, guint data_id, const gchar *string )
-{
-	static const gchar *thisfn = "na_factory_object_set_from_string";
-
-	g_return_if_fail( NA_IS_IFACTORY_OBJECT( object ));
-
-	NADataBoxed *boxed = data_boxed_from_name( object, data_id );
-	if( boxed ){
-		na_data_boxed_set_from_string( boxed, string );
-
-	} else {
-		g_warning( "%s: unknown property id %d", thisfn, data_id );
-	}
-}
-#endif
-
 static void
 attach_boxed_to_object( NAIFactoryObject *object, NADataBoxed *boxed )
 {
diff --git a/src/core/na-iduplicable.c b/src/core/na-iduplicable.c
index d71d783..fcd566b 100644
--- a/src/core/na-iduplicable.c
+++ b/src/core/na-iduplicable.c
@@ -301,6 +301,7 @@ na_iduplicable_check_status( const NAIDuplicable *object )
 	static const gchar *thisfn = "na_iduplicable_check_status";
 	DuplicableStr *str;
 	gboolean was_modified, was_valid;
+	gboolean changed;
 
 	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( NA_IS_IDUPLICABLE( object ));
@@ -311,6 +312,7 @@ na_iduplicable_check_status( const NAIDuplicable *object )
 
 		was_modified = str->modified;
 		was_valid = str->valid;
+		changed = FALSE;
 
 		if( str->origin ){
 			str->modified = !v_are_equal( str->origin, object );
@@ -318,12 +320,28 @@ na_iduplicable_check_status( const NAIDuplicable *object )
 
 		str->valid = v_is_valid( object );
 
-		if(( was_valid && !str->valid ) ||
-			( !was_valid && str->valid ) ||
-			( was_modified && !str->modified ) ||
-			( !was_modified && str->modified )){
+		if( was_modified && !str->modified ){
+			g_debug( "%s: %p (%s) status changed to non-modified",
+					thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+			changed = TRUE;
+		} else if ( !was_modified && str->modified ){
+			g_debug( "%s: %p (%s) status changed to modified",
+					thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+			changed = TRUE;
+		}
+
+		if( was_valid && !str->valid ){
+			g_debug( "%s: %p (%s) status changed to non-valid",
+					thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+			changed = TRUE;
+		} else if( !was_valid && str->valid ){
+			g_debug( "%s: %p (%s) status changed to valid",
+					thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+			changed = TRUE;
+		}
 
-				g_signal_emit_by_name( G_OBJECT( object ), NA_IDUPLICABLE_SIGNAL_STATUS_CHANGED, object );
+		if( changed ){
+			g_signal_emit_by_name( G_OBJECT( object ), NA_IDUPLICABLE_SIGNAL_STATUS_CHANGED, object );
 		}
 
 #if 0
@@ -440,6 +458,31 @@ na_iduplicable_set_origin( NAIDuplicable *object, const NAIDuplicable *origin )
 	}
 }
 
+/**
+ * na_iduplicable_set_modified:
+ * @object: the #NAIDuplicable object whose modification status is to be set.
+ * @modified: the new modification status #NAIDuplicable.
+ *
+ * Sets the new modified of a duplicated #NAIDuplicable.
+ */
+void
+na_iduplicable_set_modified( NAIDuplicable *object, gboolean modified )
+{
+	DuplicableStr *str;
+
+	g_return_if_fail( NA_IS_IDUPLICABLE( object ));
+
+	if( st_initialized && !st_finalized ){
+
+		str = get_duplicable_str( object );
+
+		if( str->modified != modified ){
+			str->modified = modified;
+			g_signal_emit_by_name( G_OBJECT( object ), NA_IDUPLICABLE_SIGNAL_STATUS_CHANGED, object );
+		}
+	}
+}
+
 static void
 v_copy( NAIDuplicable *target, const NAIDuplicable *source )
 {
@@ -502,13 +545,16 @@ status_changed_handler( NAIDuplicable *instance, gpointer user_data )
 static void
 propagate_signal_to_consumers( const gchar *signal, NAIDuplicable *instance, gpointer user_data )
 {
+	static const gchar *thisfn = "na_iduplicable_propagate_signals_to_consumers";
 	GList *ic;
 
+	g_return_if_fail( st_interface );
+
 	if( st_initialized && !st_finalized ){
 
-		g_return_if_fail( st_interface );
-		for( ic = st_interface->private->consumers ; ic ; ic = ic->next ){
+		g_debug( "%s: signal=%s, instance=%p, user_data=%p", thisfn, signal, ( void * ) instance, ( void * ) user_data );
 
+		for( ic = st_interface->private->consumers ; ic ; ic = ic->next ){
 			g_signal_emit_by_name( ic->data, signal, user_data );
 		}
 	}
diff --git a/src/core/na-object-action-factory.c b/src/core/na-object-action-factory.c
index 2cadb64..fb61349 100644
--- a/src/core/na-object-action-factory.c
+++ b/src/core/na-object-action-factory.c
@@ -105,7 +105,7 @@ static NADataDef data_def_action [] = {
 				"Label of the action in the toolbar. " \
 				"Defaults to main label if empty or not set.",
 				NAFD_TYPE_LOCALE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
diff --git a/src/core/na-object-action.c b/src/core/na-object-action.c
index 16a8b4e..75b590c 100644
--- a/src/core/na-object-action.c
+++ b/src/core/na-object-action.c
@@ -472,6 +472,7 @@ na_object_action_new( void )
 	NAObjectAction *action;
 
 	action = g_object_new( NA_OBJECT_ACTION_TYPE, NULL );
+	na_factory_object_set_defaults( NA_IFACTORY_OBJECT( action ));
 
 	return( action );
 }
@@ -515,7 +516,6 @@ na_object_action_new_with_defaults( void )
 	na_object_set_new_id( action, NULL );
 	na_object_set_label( action, NEW_NAUTILUS_ACTION );
 	na_object_set_toolbar_label( action, NEW_NAUTILUS_ACTION );
-	na_factory_object_set_defaults( NA_IFACTORY_OBJECT( action ));
 
 	profile = na_object_profile_new_with_defaults();
 	na_object_action_attach_profile( action, profile );
diff --git a/src/core/na-object-item-factory.c b/src/core/na-object-item-factory.c
index ea0a048..c834324 100644
--- a/src/core/na-object-item-factory.c
+++ b/src/core/na-object-item-factory.c
@@ -46,7 +46,7 @@ NADataDef data_def_item [] = {
 				"Main label of the NAObjectItem object. " \
 				"Serves as a default for the toolbar label of an action.",
 				NAFD_TYPE_LOCALE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
@@ -60,7 +60,7 @@ NADataDef data_def_item [] = {
 				"Item tooltip",
 				"Tooltip associated to the item in the context menu or in the toolbar.",
 				NAFD_TYPE_LOCALE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
@@ -75,7 +75,7 @@ NADataDef data_def_item [] = {
 				"Icon displayed in the context menu and in the toolbar. " \
 				"May be the name of a themed icon, or the full path to any appropriate image.",
 				NAFD_TYPE_LOCALE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
@@ -90,7 +90,7 @@ NADataDef data_def_item [] = {
 				"Some text which explains the goal of the menu or the action. " \
 				"Will be used, e.g. when displaying available items on a web site.",
 				NAFD_TYPE_LOCALE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
diff --git a/src/core/na-object-item.c b/src/core/na-object-item.c
index 33f32c5..f765f1c 100644
--- a/src/core/na-object-item.c
+++ b/src/core/na-object-item.c
@@ -277,7 +277,7 @@ na_object_item_copy( NAObjectItem *item, const NAObjectItem *source )
 
 /**
  * na_object_item_are_equal:
- * @a: the first #NAObjectItem instance.
+ * @a: the first (original) #NAObjectItem instance.
  * @b: the second #NAObjectItem instance.
  *
  * Returns: %TRUE if @a is equal to @b.
@@ -286,14 +286,18 @@ na_object_item_copy( NAObjectItem *item, const NAObjectItem *source )
  * and is triggered after all comparable elementary data (in #NAIFactoryObject
  * sense) have already been successfully compared.
  *
- * We have to deal here with the subitems: comparing childs by their ids
+ * We have to deal here with the subitems: comparing children by their ids
  * between @a and @b.
+ *
+ * Note that, when called from na_object_check_status, the status of children
+ * have already been checked, and so we should be able to rely on them.
  */
 gboolean
 na_object_item_are_equal( const NAObjectItem *a, const NAObjectItem *b )
 {
+	static const gchar *thisfn = "na_object_item_are_equal";
 	gboolean equal;
-	GList *a_childs, *b_childs, *it;
+	GList *a_children, *b_children, *it;
 	gchar *first_id, *second_id;
 	NAObjectId *first_obj, *second_obj;
 	gint first_pos, second_pos;
@@ -310,51 +314,62 @@ na_object_item_are_equal( const NAObjectItem *a, const NAObjectItem *b )
 		equal = TRUE;
 
 		if( equal ){
-			a_childs = na_object_get_items( a );
-			b_childs = na_object_get_items( b );
-			equal = ( g_list_length( a_childs ) == g_list_length( b_childs ));
+			a_children = na_object_get_items( a );
+			b_children = na_object_get_items( b );
+			equal = ( g_list_length( a_children ) == g_list_length( b_children ));
+			if( !equal ){
+				g_debug( "%s: %p (%s) not equal as g_list_length not equal",
+						thisfn, ( void * ) b, G_OBJECT_TYPE_NAME( b ));
+			}
 		}
 
 		if( equal ){
-			for( it = a_childs ; it && equal ; it = it->next ){
+			for( it = a_children ; it && equal ; it = it->next ){
 				first_id = na_object_get_id( it->data );
 				second_obj = na_object_get_item( b, first_id );
 				first_pos = -1;
 				second_pos = -1;
+
 				if( second_obj ){
-					first_pos = g_list_position( a_childs, it );
-					second_list = g_list_find( b_childs, second_obj );
-					second_pos = g_list_position( b_childs, second_list );
-#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-					g_debug( "na_object_item_are_equal: first_pos=%u, second_pos=%u", first_pos, second_pos );
-#endif
+					first_pos = g_list_position( a_children, it );
+					second_list = g_list_find( b_children, second_obj );
+					second_pos = g_list_position( b_children, second_list );
+
 					if( first_pos != second_pos ){
 						equal = FALSE;
-						/*g_debug( "first_id=%s, first_pos=%d, second_pos=%d", first_id, first_pos, second_pos );*/
+						g_debug( "%s: %p (%s) not equal as child %s is at pos %u",
+								thisfn, ( void * ) b, G_OBJECT_TYPE_NAME( b ), first_id, second_pos );
 					}
+
 				} else {
-#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-					g_debug( "na_object_item_are_equal: id=%s not found in b", first_id );
-#endif
 					equal = FALSE;
-					/*g_debug( "first_id=%s, second not found", first_id );*/
+					g_debug( "%s: %p (%s) not equal as child %s removed",
+							thisfn, ( void * ) b, G_OBJECT_TYPE_NAME( b ), first_id );
 				}
-				/*g_debug( "first_id=%s first_pos=%d second_pos=%d", first_id, first_pos, second_pos );*/
+
 				g_free( first_id );
 			}
 		}
 
 		if( equal ){
-			for( it = b_childs ; it && equal ; it = it->next ){
+			for( it = b_children ; it && equal ; it = it->next ){
 				second_id = na_object_get_id( it->data );
 				first_obj = na_object_get_item( a, second_id );
+
 				if( !first_obj ){
-#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-					g_debug( "na_object_item_are_equal: id=%s not found in a", second_id );
-#endif
 					equal = FALSE;
-					/*g_debug( "second_id=%s, first not found", second_id );*/
+					g_debug( "%s: %p (%s) not equal as child %s added",
+							thisfn, ( void * ) b, G_OBJECT_TYPE_NAME( b ), second_id );
+
+				} else {
+					equal = !na_object_is_modified( it->data );
+
+					if( !equal ){
+						g_debug( "%s: %p (%s) not equal as child %s modified",
+								thisfn, ( void * ) b, G_OBJECT_TYPE_NAME( b ), second_id );
+					}
 				}
+
 				g_free( second_id );
 			}
 		}
@@ -641,7 +656,9 @@ na_object_item_count_items( GList *items, gint *menus, gint *actions, gint *prof
  * na_object_item_unref_items:
  * @list: a list of #NAObject-derived items.
  *
- * Recursively unref the #NAObject of the list, freeing the list at last.
+ * Unref only the first level the #NAObject of the list, freeing the list at last.
+ *
+ * This is rather only used by #NAPivot.
  */
 void
 na_object_item_unref_items( GList *items )
@@ -649,7 +666,6 @@ na_object_item_unref_items( GList *items )
 	GList *it;
 
 	for( it = items ; it ; it = it->next ){
-		/*na_object_unref( it->data );*/
 		g_object_unref( it->data );
 	}
 
@@ -657,6 +673,26 @@ na_object_item_unref_items( GList *items )
 }
 
 /**
+ * na_object_item_unref_items_rec:
+ * @list: a list of #NAObject-derived items.
+ *
+ * Recursively unref the #NAObject of the list, freeing the list at last.
+ *
+ * This is heavily used by NACT.
+ */
+void
+na_object_item_unref_items_rec( GList *items )
+{
+	GList *it;
+
+	for( it = items ; it ; it = it->next ){
+		na_object_unref( it->data );
+	}
+
+	g_list_free( items );
+}
+
+/**
  * na_object_item_factory_write_start:
  * @item: this #NAObjectItem-derived object.
  *
diff --git a/src/core/na-object-menu.c b/src/core/na-object-menu.c
index dc00ed7..efda2e0 100644
--- a/src/core/na-object-menu.c
+++ b/src/core/na-object-menu.c
@@ -386,6 +386,7 @@ na_object_menu_new( void )
 	NAObjectMenu *menu;
 
 	menu = g_object_new( NA_OBJECT_MENU_TYPE, NULL );
+	na_factory_object_set_defaults( NA_IFACTORY_OBJECT( menu ));
 
 	return( menu );
 }
@@ -404,7 +405,6 @@ na_object_menu_new_with_defaults( void )
 
 	na_object_set_new_id( menu, NULL );
 	na_object_set_label( menu, NEW_NAUTILUS_MENU );
-	na_factory_object_set_defaults( NA_IFACTORY_OBJECT( menu ));
 
 	return( menu );
 }
diff --git a/src/core/na-object-profile-factory.c b/src/core/na-object-profile-factory.c
index f452dbc..b033ec8 100644
--- a/src/core/na-object-profile-factory.c
+++ b/src/core/na-object-profile-factory.c
@@ -32,8 +32,6 @@
 #include <config.h>
 #endif
 
-#include <glib/gi18n.h>
-
 #include <api/na-ifactory-object-data.h>
 #include <api/na-data-def.h>
 #include <api/na-data-types.h>
@@ -48,7 +46,7 @@ static NADataDef data_def_profile [] = {
 				"Main label of the NAObjectProfile profile. " \
 				"May be used as a description for the function of the profile.",
 				NAFD_TYPE_LOCALE_STRING,
-				N_( "Default profile" ),
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
@@ -62,7 +60,7 @@ static NADataDef data_def_profile [] = {
 				"Command path",
 				"The path to the command.",
 				NAFD_TYPE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				TRUE,
@@ -76,7 +74,7 @@ static NADataDef data_def_profile [] = {
 				"Command parameters",
 				"The parameters of the command.",
 				NAFD_TYPE_STRING,
-				NULL,
+				"",
 				TRUE,
 				TRUE,
 				FALSE,
diff --git a/src/core/na-object-profile.c b/src/core/na-object-profile.c
index d594f23..17686bb 100644
--- a/src/core/na-object-profile.c
+++ b/src/core/na-object-profile.c
@@ -32,6 +32,7 @@
 #include <config.h>
 #endif
 
+#include <glib/gi18n.h>
 #include <string.h>
 
 #include <libnautilus-extension/nautilus-file-info.h>
@@ -515,6 +516,7 @@ na_object_profile_new( void )
 	NAObjectProfile *profile;
 
 	profile = g_object_new( NA_OBJECT_PROFILE_TYPE, NULL );
+	na_factory_object_set_defaults( NA_IFACTORY_OBJECT( profile ));
 
 	return( profile );
 }
@@ -532,7 +534,7 @@ na_object_profile_new_with_defaults( void )
 	NAObjectProfile *profile = na_object_profile_new();
 
 	na_object_set_id( profile, "profile-zero" );
-	na_factory_object_set_defaults( NA_IFACTORY_OBJECT( profile ));
+	na_object_set_label( profile, _( "Default profile" ));
 
 	return( profile );
 }
diff --git a/src/core/na-object.c b/src/core/na-object.c
index 9faae4e..5d77ff3 100644
--- a/src/core/na-object.c
+++ b/src/core/na-object.c
@@ -76,6 +76,7 @@ static gboolean       iduplicable_are_equal_iter( GObjectClass *class, const NAO
 static gboolean       iduplicable_is_valid( const NAIDuplicable *object );
 static gboolean       iduplicable_is_valid_iter( GObjectClass *class, const NAObject *a, HierarchyIter *str );
 
+static void           push_modified_status_up( const NAObject *object, gboolean is_modified );
 static gboolean       dump_class_hierarchy_iter( GObjectClass *class, const NAObject *object, void *user_data );
 static void           dump_tree( GList *tree, gint level );
 static void           iter_on_class_hierarchy( const NAObject *object, HierarchyIterFunc pfn, void *user_data );
@@ -435,21 +436,41 @@ na_object_object_check_status_up( const NAObject *object )
 		is_modified = na_object_is_modified( object );
 		is_valid = na_object_is_valid( object );
 
-		parent = na_object_get_parent( object );
-		if( parent ){
-			na_object_check_status_up( parent );
+		/* if a child becomes modified, then we can safely push this 'modified'
+		 * status up to all its parent hierarchy
+		 */
+		if( !was_modified && is_modified ){
+			push_modified_status_up( object, is_modified );
 		}
 
-		changed =
-			( was_modified && !is_modified ) ||
-			( !was_modified && is_modified ) ||
-			( was_valid && !is_valid ) ||
-			( !was_valid && is_valid );
+		/* but if a child becomes non modified, or its validity status changes,
+		 * then we have to recompute these status for all the parent hierarchy
+		 */
+		changed = (( was_valid && !is_valid ) ||
+				( !was_valid && is_valid ) ||
+				( was_modified && !is_modified ));
+
+		if( changed ){
+			parent = na_object_get_parent( object );
+			if( parent ){
+				na_object_check_status_up( parent );
+			}
+		}
 	}
 
 	return( changed );
 }
 
+static void
+push_modified_status_up( const NAObject *object, gboolean is_modified )
+{
+	NAObject *parent = ( NAObject * ) na_object_get_parent( object );
+	if( parent ){
+		na_iduplicable_set_modified( NA_IDUPLICABLE( parent ), is_modified );
+		push_modified_status_up( parent, is_modified );
+	}
+}
+
 /**
  * na_object_object_dump:
  * @object: the #NAObject-derived object to be dumped.
@@ -564,19 +585,19 @@ dump_tree( GList *tree, gint level )
  * @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.
+ * Recursively reset origin of @object and its children to @origin (and
+ * its children), so that @origin appears 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.
+ * and thus we do not have to check if children lists are equal.
  */
 void
 na_object_object_reset_origin( NAObject *object, const NAObject *origin )
 {
-	GList *origin_childs, *iorig;
-	GList *object_childs, *iobj;
+	GList *origin_children, *iorig;
+	GList *object_children, *iobj;
 	NAObject *orig_object;
 
 	g_return_if_fail( NA_IS_OBJECT( origin ));
@@ -584,9 +605,9 @@ na_object_object_reset_origin( NAObject *object, const NAObject *origin )
 
 	if( !object->private->dispose_has_run && !origin->private->dispose_has_run ){
 
-		origin_childs = na_object_get_items( origin );
-		object_childs = na_object_get_items( object );
-		for( iorig = origin_childs, iobj = object_childs ; iorig && iobj ; iorig = iorig->next, iobj = iobj->next ){
+		origin_children = na_object_get_items( origin );
+		object_children = na_object_get_items( object );
+		for( iorig = origin_children, iobj = object_children ; iorig && iobj ; iorig = iorig->next, iobj = iobj->next ){
 			orig_object = ( NAObject * ) na_object_get_origin( iorig->data );
 			g_return_if_fail( orig_object == iobj->data );
 			na_object_reset_origin( iobj->data, iorig->data );
diff --git a/src/core/na-pivot.c b/src/core/na-pivot.c
index 240fe2b..1f89a3d 100644
--- a/src/core/na-pivot.c
+++ b/src/core/na-pivot.c
@@ -312,7 +312,7 @@ instance_dispose( GObject *object )
 		self->private->consumers = NULL;
 
 		/* release item tree */
-		na_object_unref_items( self->private->tree );
+		na_object_item_unref_items( self->private->tree );
 		self->private->tree = NULL;
 
 		/* release the GConf monitoring */
@@ -545,7 +545,7 @@ na_pivot_load_items( NAPivot *pivot )
 
 	if( !pivot->private->dispose_has_run ){
 
-		na_object_unref_items( pivot->private->tree );
+		na_object_item_unref_items( pivot->private->tree );
 
 		messages = NULL;
 
diff --git a/src/core/na-updater.c b/src/core/na-updater.c
index 2663985..dc74746 100644
--- a/src/core/na-updater.c
+++ b/src/core/na-updater.c
@@ -241,7 +241,7 @@ na_updater_remove_item( NAUpdater *updater, NAObject *item )
 		g_object_set( G_OBJECT( updater ), NAPIVOT_PROP_TREE, &tree, NULL );
 
 		if( G_IS_OBJECT( item )){
-			na_object_unref( item );
+			g_object_unref( item );
 		}
 	}
 }
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index a603d23..aa4b4b9 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -877,6 +877,7 @@ display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *m
 	label = na_object_get_label( object );
 	g_object_set( cell, "style-set", FALSE, NULL );
 	g_object_set( cell, "foreground-set", FALSE, NULL );
+	/*g_debug( "nact_iactions_list_display_label: %s %s", G_OBJECT_TYPE_NAME( object ), label );*/
 
 	if( ialid->management_mode == IACTIONS_LIST_MANAGEMENT_MODE_EDITION ){
 



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