[nautilus-actions] Fix check_edition_status dynamic



commit 7feb513f5947889ee49b4ae96033976b74f5ae07
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Sep 21 06:57:05 2009 +0200

    Fix check_edition_status dynamic
    
    Also fix selection of newly inserted profile.

 ChangeLog                      |   38 +++++++++++++++
 src/common/na-gconf-provider.c |    9 ++--
 src/common/na-iduplicable.c    |   81 +++++++++++++++++++++++++++++--
 src/common/na-iduplicable.h    |    3 +
 src/common/na-iio-provider.c   |   37 +++++++++-----
 src/common/na-obj-action.c     |   26 ++++++++++-
 src/common/na-object-item.c    |   26 +++++++---
 src/common/na-object.c         |   11 +++--
 src/nact/nact-iactions-list.c  |  103 +++++++++++++++++++++++++++++----------
 src/nact/nact-main-menubar.c   |   22 ++++++--
 src/nact/nact-tree-model.c     |   30 +++++++-----
 src/nact/nact-tree-model.h     |    2 +-
 12 files changed, 304 insertions(+), 84 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b337b63..9e40140 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2009-09-21 Pierre Wieser <pwieser trychlos org>
+
+	* src/common/na-gconf-provider.c (write_item_menu):
+	Fix memory leak.
+
+	* src/common/na-iduplicable.c:
+	* src/common/na-iduplicable.h:
+	Emits a signal for each modification of one of the status.
+	Do not use NA_xx macros when returning a pointer that may be NULL.
+
+	* src/common/na-iio-provider.c (build_hierarchy):
+	Defaults to keep the whole list when there is no level-zero pref.
+
+	* src/common/na-obj-action.c:
+	Version number is not localized, so compare should be ascii.
+	Action inherits from edition status of its profiles.
+
+	* src/common/na-object-item.c:
+	Optimizes check of edition status of subitems.
+
+	* src/common/na-object.c:
+	No more over-checks edition status of item's childs.
+
+	* src/nact/nact-iactions-list.c:
+	When duplicating an object, try to insert the new one besides
+	the original one.
+
+	* src/nact/nact-main-menubar.c (on_new_profile_activated):
+	Setup edition status of new profile.
+
+	* src/nact/nact-main-menubar.c (save_object_item):
+	Cleanup the code.
+
+	* src/nact/nact-tree-model.c:
+	* src/nact/nact-tree-model.h (nact_tree_model_insert):
+	Returns the path string of the newly inserted row, as it appears
+	more liable that an iter after child model conversion.
+
 2009-09-20 Pierre Wieser <pwieser trychlos org>
 
 	* src/common/na-object-item.c (object_id_new_id):
diff --git a/src/common/na-gconf-provider.c b/src/common/na-gconf-provider.c
index 5b6c124..2b470f5 100644
--- a/src/common/na-gconf-provider.c
+++ b/src/common/na-gconf-provider.c
@@ -835,18 +835,17 @@ write_item_menu( NAGConfProvider *provider, const NAObjectMenu *menu, gchar **me
 {
 	gchar *uuid;
 	gboolean ret;
-	GSList *ids;
 
 	if( !write_object_item( provider, NA_OBJECT_ITEM( menu ), message )){
 		return( FALSE );
 	}
 
 	uuid = na_object_get_id( NA_OBJECT( menu ));
-	ids = na_object_menu_rebuild_items_list( menu );
-	ret = write_list( provider, uuid, NULL, MENU_ITEMS_ENTRY, ids, message );
-	na_utils_free_string_list( ids );
-	g_free( uuid );
 
+	ret =
+		write_list( provider, uuid, NULL, MENU_ITEMS_ENTRY, na_object_menu_rebuild_items_list( menu ), message );
+
+	g_free( uuid );
 	return( ret );
 }
 
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
index 8e6d9c6..dcef11b 100644
--- a/src/common/na-iduplicable.c
+++ b/src/common/na-iduplicable.c
@@ -46,8 +46,17 @@ struct NAIDuplicableInterfacePrivate {
 #define NA_IDUPLICABLE_PROP_IS_MODIFIED		"na-iduplicable-is-modified"
 #define NA_IDUPLICABLE_PROP_IS_VALID		"na-iduplicable-is-valid"
 
+/* signals emitted on NAIDuplicable when a status changes
+ */
+enum {
+	MODIFIED_CHANGED,
+	VALID_CHANGED,
+	LAST_SIGNAL
+};
+
 static gboolean st_initialized = FALSE;
 static gboolean st_finalized = FALSE ;
+static gint     st_signals[ LAST_SIGNAL ] = { 0 };
 
 static GType          register_type( void );
 static void           interface_base_init( NAIDuplicableInterface *klass );
@@ -115,6 +124,42 @@ interface_base_init( NAIDuplicableInterface *klass )
 
 		klass->private = g_new0( NAIDuplicableInterfacePrivate, 1 );
 
+		/**
+		 * na-iduplicable-modified-changed:
+		 *
+		 * This signal is emitted byIDuplicable when the modification
+		 * status of an object has been modified.
+		 */
+		st_signals[ MODIFIED_CHANGED ] = g_signal_new(
+				NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED,
+				G_TYPE_OBJECT,
+				G_SIGNAL_RUN_LAST,
+				0,
+				NULL,
+				NULL,
+				g_cclosure_marshal_VOID__POINTER,
+				G_TYPE_NONE,
+				1,
+				G_TYPE_POINTER );
+
+		/**
+		 * na-iduplicable-valid-changed:
+		 *
+		 * This signal is emitted byIDuplicable when the validity
+		 * status of an object has been modified.
+		 */
+		st_signals[ VALID_CHANGED ] = g_signal_new(
+				NA_IDUPLICABLE_SIGNAL_VALID_CHANGED,
+				G_TYPE_OBJECT,
+				G_SIGNAL_RUN_LAST,
+				0,
+				NULL,
+				NULL,
+				g_cclosure_marshal_VOID__POINTER,
+				G_TYPE_NONE,
+				1,
+				G_TYPE_POINTER );
+
 		st_initialized = TRUE;
 	}
 }
@@ -239,23 +284,25 @@ na_iduplicable_duplicate( const NAIDuplicable *object )
 void
 na_iduplicable_check_edition_status( const NAIDuplicable *object )
 {
-	/*static const gchar *thisfn = "na_iduplicable_check_edition_status";
-	g_debug( "%s: object=%p", thisfn, object );*/
+	static const gchar *thisfn = "na_iduplicable_check_edition_status";
 	gboolean modified = TRUE;
 	NAIDuplicable *origin;
 	gboolean valid;
 
+	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 	g_return_if_fail( st_initialized && !st_finalized );
 	g_return_if_fail( NA_IS_IDUPLICABLE( object ));
 
 	origin = get_origin( object );
 	if( origin ){
-		modified = !v_are_equal( object, origin );
+		modified = !v_are_equal( origin, object );
 	}
 	set_modified( object, modified );
 
 	valid = v_is_valid( object );
 	set_valid( object, valid );
+	g_debug( "%s: object=%p, modified=%s, valid=%s",
+			thisfn, ( void * ) object, modified ? "True":"False", valid ? "True":"False" );
 }
 
 /**
@@ -394,10 +441,15 @@ get_modified( const NAIDuplicable *object )
 	return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_MODIFIED )));
 }
 
+/*
+ * do not use here NA_IDUPLICABLE macro as it may return a (valid) NULL
+ * value
+ */
 static NAIDuplicable *
 get_origin( const NAIDuplicable *object )
 {
-	return( NA_IDUPLICABLE( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_ORIGIN )));
+	/*return( NA_IDUPLICABLE( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_ORIGIN )));*/
+	return(( NAIDuplicable * ) g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_ORIGIN ));
 }
 
 static gboolean
@@ -406,10 +458,22 @@ get_valid( const NAIDuplicable *object )
 	return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_VALID )));
 }
 
+/*
+ * I'd wish simulate the behavior of GObject property which is able to
+ * send a message each time a property is changed ; but these data are
+ * not properties of NAObject
+ */
 static void
 set_modified( const NAIDuplicable *object, gboolean is_modified )
 {
-	g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_MODIFIED, GUINT_TO_POINTER( is_modified ));
+	gboolean was_modified = get_modified( object );
+
+	if( was_modified != is_modified ){
+		g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_MODIFIED, GUINT_TO_POINTER( is_modified ));
+		g_signal_emit_by_name( G_OBJECT( object ), NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED, object );
+		g_debug( "na_iduplicable_set_modified: object=%p (%s) modified=%s",
+				( void * ) object, G_OBJECT_TYPE_NAME( object ), is_modified ? "True":"False" );
+	}
 }
 
 static void
@@ -421,5 +485,10 @@ set_origin( const NAIDuplicable *object, const NAIDuplicable *origin )
 static void
 set_valid( const NAIDuplicable *object, gboolean is_valid )
 {
-	g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_VALID, GUINT_TO_POINTER( is_valid ));
+	gboolean was_valid = get_valid( object );
+
+	if( was_valid != is_valid ){
+		g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_VALID, GUINT_TO_POINTER( is_valid ));
+		g_signal_emit_by_name( G_OBJECT( object ), NA_IDUPLICABLE_SIGNAL_VALID_CHANGED, object );
+	}
 }
diff --git a/src/common/na-iduplicable.h b/src/common/na-iduplicable.h
index ea638f5..2c869bb 100644
--- a/src/common/na-iduplicable.h
+++ b/src/common/na-iduplicable.h
@@ -142,6 +142,9 @@ typedef struct {
 }
 	NAIDuplicableInterface;
 
+#define NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED	"na-iduplicable-modified-changed"
+#define NA_IDUPLICABLE_SIGNAL_VALID_CHANGED		"na-iduplicable-valid-changed"
+
 GType          na_iduplicable_get_type( void );
 
 void           na_iduplicable_init( NAIDuplicable *object );
diff --git a/src/common/na-iio-provider.c b/src/common/na-iio-provider.c
index e7f5081..ca17012 100644
--- a/src/common/na-iio-provider.c
+++ b/src/common/na-iio-provider.c
@@ -197,23 +197,32 @@ build_hierarchy( GList *tree, GSList *level_zero )
 
 	hierarchy = NULL;
 
-	for( ilevel = level_zero ; ilevel ; ilevel = ilevel->next ){
-		g_debug( "na_iio_provider_build_hierarchy: next_level_zero uuid is %s", ( gchar * ) ilevel->data );
-		it = g_list_find_custom( tree, ilevel->data, ( GCompareFunc ) search_item );
-		if( it ){
-			hierarchy = g_list_append( hierarchy, g_object_ref( it->data ));
-			g_debug( "na_iio_provider_build_hierarchy: appending %s at %p to hierarchy %p",
-					G_OBJECT_TYPE_NAME( it->data ), ( void * ) it->data, ( void * ) hierarchy );
-
-			if( NA_IS_OBJECT_MENU( it->data )){
-				subitems_ids = na_object_menu_get_items_list( NA_OBJECT_MENU( it->data ));
-				subitems = build_hierarchy( tree, subitems_ids );
-				na_object_set_items( it->data, subitems );
-				na_object_free_items( subitems );
-				na_utils_free_string_list( subitems_ids );
+	if( g_slist_length( level_zero )){
+		for( ilevel = level_zero ; ilevel ; ilevel = ilevel->next ){
+			g_debug( "na_iio_provider_build_hierarchy: next_level_zero uuid is %s", ( gchar * ) ilevel->data );
+			it = g_list_find_custom( tree, ilevel->data, ( GCompareFunc ) search_item );
+			if( it ){
+				hierarchy = g_list_append( hierarchy, g_object_ref( it->data ));
+				g_debug( "na_iio_provider_build_hierarchy: appending %s at %p to hierarchy %p",
+						G_OBJECT_TYPE_NAME( it->data ), ( void * ) it->data, ( void * ) hierarchy );
+
+				if( NA_IS_OBJECT_MENU( it->data )){
+					subitems_ids = na_object_menu_get_items_list( NA_OBJECT_MENU( it->data ));
+					subitems = build_hierarchy( tree, subitems_ids );
+					na_object_set_items( it->data, subitems );
+					na_object_free_items( subitems );
+					na_utils_free_string_list( subitems_ids );
+				}
 			}
 		}
 	}
+	/* if level-zero list is empty, we consider that all actions go to it
+	 */
+	else {
+		for( it = tree ; it ; it = it->next ){
+			hierarchy = g_list_append( hierarchy, g_object_ref( it->data ));
+		}
+	}
 
 	return( hierarchy );
 }
diff --git a/src/common/na-obj-action.c b/src/common/na-obj-action.c
index 8231003..5bc235f 100644
--- a/src/common/na-obj-action.c
+++ b/src/common/na-obj-action.c
@@ -547,11 +547,21 @@ object_copy( NAObject *target, const NAObject *source )
 	/*g_debug( "na_object_action_object_copy: end" );*/
 }
 
+/*
+ * note 1: version is not localized (see configure.ac)
+ *
+ * note 2: when checking for equality of profiles, we know that NAObjectItem
+ * has already checked their edition status, and assert that profiles lists
+ * were the sames ; we so only report the modification status to the action
+ */
 static gboolean
 object_are_equal( const NAObject *a, const NAObject *b )
 {
 	NAObjectAction *first, *second;
 	gboolean equal = TRUE;
+	GList *profiles, *ip;
+	gchar *id;
+	NAObjectProfile *profile;
 
 	g_return_val_if_fail( NA_IS_OBJECT_ACTION( a ), FALSE );
 	g_return_val_if_fail( !NA_OBJECT_ACTION( a )->private->dispose_has_run, FALSE );
@@ -562,7 +572,21 @@ object_are_equal( const NAObject *a, const NAObject *b )
 	second = NA_OBJECT_ACTION( b );
 
 	if( equal ){
-		equal = ( g_utf8_collate( first->private->version, second->private->version ) == 0 );
+		equal = ( strcmp( first->private->version, second->private->version ) == 0 );
+	}
+
+	if( equal ){
+		profiles = na_object_get_items( a );
+		for( ip = profiles ; ip ; ip = ip->next ){
+			id = na_object_get_id( ip->data );
+			profile = NA_OBJECT_PROFILE( na_object_get_item( b, id ));
+			equal = !na_object_is_modified( profile );
+			if( !equal ){
+				g_debug( "na_object_action_are_equal: profile=%p, equal=False", ( void * ) profile );
+			}
+			g_free( id );
+		}
+		na_object_free_items( profiles );
 	}
 
 	/*g_debug( "na_object_action_are_equal: %s", equal ? "True":"False" );*/
diff --git a/src/common/na-object-item.c b/src/common/na-object-item.c
index 0426209..bcf7d0c 100644
--- a/src/common/na-object-item.c
+++ b/src/common/na-object-item.c
@@ -826,7 +826,19 @@ object_copy( NAObject *target, const NAObject *source )
 }
 
 /*
- * note that provider is not consider as pertinent here
+ * @a: original object.
+ * @b: the object which has been initially duplicated from @a, and is
+ * being checked for modification status.
+ *
+ * note 1: The provider is not considered as pertinent here
+ *
+ * note 2: NAObjectItem recursively checks for equality in subitems.
+ * Nonetheless, the modification status of subitems doesn't have any
+ * impact on this object itself, provided that subitems lists are
+ * themselves identical
+ *
+ * note 3: Only NAObjectAction is modified that one of the profiles are
+ * modified (because they are saved as a whole)
  */
 static gboolean
 object_are_equal( const NAObject *a, const NAObject *b )
@@ -860,11 +872,12 @@ object_are_equal( const NAObject *a, const NAObject *b )
 		for( it = NA_OBJECT_ITEM( a )->private->items ; it && equal ; it = it->next ){
 			first_obj = NA_OBJECT( it->data );
 			first_id = na_object_get_id( first_obj );
-			second_obj = NA_OBJECT( na_object_get_item( b, first_id ));
+			second_obj = ( NAObject * ) na_object_get_item( b, first_id );
 			g_free( first_id );
 			if( second_obj ){
-				equal = na_object_iduplicable_are_equal( first_obj, second_obj );
+				na_object_check_edition_status( second_obj );
 			} else {
+				g_debug( "na_object_item_are_equal: object=%p (%s), equal=False", ( void * ) b, G_OBJECT_TYPE_NAME( b ));
 				equal = FALSE;
 			}
 		}
@@ -874,11 +887,10 @@ object_are_equal( const NAObject *a, const NAObject *b )
 		for( it = NA_OBJECT_ITEM( b )->private->items ; it && equal ; it = it->next ){
 			second_obj = NA_OBJECT( it->data );
 			second_id = na_object_get_id( second_obj );
-			first_obj = NA_OBJECT( na_object_get_item( a, second_id ));
+			first_obj = ( NAObject * ) na_object_get_item( a, second_id );
 			g_free( second_id );
-			if( first_obj ){
-				equal = na_object_iduplicable_are_equal( first_obj, second_obj );
-			} else {
+			if( !first_obj ){
+				g_debug( "na_object_item_are_equal: object=%p (%s), equal=False", ( void * ) b, G_OBJECT_TYPE_NAME( b ));
 				equal = FALSE;
 			}
 		}
diff --git a/src/common/na-object.c b/src/common/na-object.c
index 46922f4..165da3e 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -635,17 +635,17 @@ do_is_valid( const NAObject *object )
 void
 na_object_iduplicable_check_edition_status( const NAObject *object )
 {
-	GList *childs, *ic;
+	/*GList *childs, *ic;*/
 
 	g_return_if_fail( NA_IS_OBJECT( object ));
 	g_return_if_fail( !object->private->dispose_has_run );
 
 	na_iduplicable_check_edition_status( NA_IDUPLICABLE( object ));
 
-	childs = v_get_childs( object );
+	/*childs = v_get_childs( object );
 	for( ic = childs ; ic ; ic = ic->next ){
 		na_iduplicable_check_edition_status( NA_IDUPLICABLE( ic->data ));
-	}
+	}*/
 }
 
 /**
@@ -696,6 +696,8 @@ na_object_iduplicable_is_valid( const NAObject *object )
  * Returns the original object which was at the origin of @object.
  *
  * Returns: a #NAObject, or NULL.
+ *
+ * Do not use here NA_OBJECT macro as it may return a (valid) NULL value
  */
 NAObject *
 na_object_iduplicable_get_origin( const NAObject *object )
@@ -703,7 +705,8 @@ na_object_iduplicable_get_origin( const NAObject *object )
 	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
 	g_return_val_if_fail( !object->private->dispose_has_run, NULL );
 
-	return( NA_OBJECT( na_iduplicable_get_origin( NA_IDUPLICABLE( object ))));
+	/*return( NA_OBJECT( na_iduplicable_get_origin( NA_IDUPLICABLE( object ))));*/
+	return(( NAObject * ) na_iduplicable_get_origin( NA_IDUPLICABLE( object )));
 }
 
 /**
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 8d23fc4..5dc466c 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -35,6 +35,7 @@
 #include <gdk/gdkkeysyms.h>
 #include <string.h>
 
+#include <common/na-iduplicable.h>
 #include <common/na-object-api.h>
 #include <common/na-obj-action.h>
 #include <common/na-obj-menu.h>
@@ -85,6 +86,15 @@ typedef struct {
 }
 	SelectionIter;
 
+/* when iterating while searching for the path of an object
+ */
+typedef struct {
+	NAObject    *object;
+	gboolean     found;
+	GtkTreePath *path;
+}
+	ObjectToPathIter;
+
 /* data set against GObject
  */
 #define SELECTION_CHANGED_SIGNAL_MODE	"nact-iactions-list-selection-changed-signal-mode"
@@ -114,6 +124,8 @@ static gboolean     have_dnd_mode( NactIActionsList *instance );
 static gboolean     have_filter_selection_mode( NactIActionsList *instance );
 static gboolean     is_selection_changed_authorized( NactIActionsList *instance );
 static void         iter_on_selection( NactIActionsList *instance, FnIterOnSelection fn_iter, gpointer user_data );
+static GtkTreePath *object_to_path( NactIActionsList *instance, NactTreeModel *model, NAObject *object );
+static gboolean     object_to_path_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ObjectToPathIter *otp );
 static gboolean     on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsList *instance );
 static gboolean     on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *instance );
 static void         on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance );
@@ -657,14 +669,18 @@ nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObj
 	model = gtk_tree_view_get_model( treeview );
 	g_return_if_fail( NACT_IS_TREE_MODEL( model ));
 
-	selection = gtk_tree_view_get_selection( treeview );
-	list_selected = gtk_tree_selection_get_selected_rows( selection, NULL );
-	if( g_list_length( list_selected )){
-		insert_path = gtk_tree_path_copy(( GtkTreePath * ) list_selected->data );
-	}
+	if( sibling ){
+		insert_path = object_to_path( instance, NACT_TREE_MODEL( model ), sibling );
 
-	g_list_foreach( list_selected, ( GFunc ) gtk_tree_path_free, NULL );
-	g_list_free( list_selected );
+	} else {
+		selection = gtk_tree_view_get_selection( treeview );
+		list_selected = gtk_tree_selection_get_selected_rows( selection, NULL );
+		if( g_list_length( list_selected )){
+			insert_path = gtk_tree_path_copy(( GtkTreePath * ) list_selected->data );
+		}
+		g_list_foreach( list_selected, ( GFunc ) gtk_tree_path_free, NULL );
+		g_list_free( list_selected );
+	}
 
 	last_path = do_insert_items( treeview, model, items, insert_path, 0, &parents );
 
@@ -684,10 +700,10 @@ do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTr
 {
 	static const gchar *thisfn = "nact_iactions_list_do_insert_items";
 	guint nb_profiles, nb_actions, nb_menus;
-	GtkTreeIter iter;
 	GList *it;
 	GList *subitems;
-	GtkTreePath *newpath;
+	gchar *inserted_path_str;
+	GtkTreePath *inserted_path;
 	NAObject *obj_parent;
 	GtkTreePath *returned_path;
 
@@ -707,17 +723,15 @@ do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTr
 			 * from store to filter_model, and ran through filter_visible function
 			 * we so cannot rely on it if object is a profile inserted at level > 0
 			 */
-			nact_tree_model_insert( NACT_TREE_MODEL( model ), NA_OBJECT( it->data ), path, &iter, &obj_parent );
+			inserted_path_str = nact_tree_model_insert( NACT_TREE_MODEL( model ), NA_OBJECT( it->data ), path, &obj_parent );
+			g_debug( "%s: inserted_path=%s", thisfn, inserted_path_str );
 
-			newpath = NULL;
-			if( !NA_IS_OBJECT_PROFILE( it->data ) || level == 0 ){
-				newpath = gtk_tree_model_get_path( model, &iter );
-			}
+			inserted_path = gtk_tree_path_new_from_string( inserted_path_str );
 
 			if( level == 0 ){
-				gtk_tree_view_expand_to_path( treeview, newpath );
+				gtk_tree_view_expand_to_path( treeview, inserted_path );
 				gtk_tree_path_free( returned_path );
-				returned_path = gtk_tree_path_copy( newpath );
+				returned_path = gtk_tree_path_copy( inserted_path );
 			}
 
 			*parents = do_insert_items_add_parent( *parents, treeview, model, obj_parent );
@@ -726,13 +740,12 @@ do_insert_items( GtkTreeView *treeview, GtkTreeModel *model, GList *items, GtkTr
 			 */
 			if( NA_IS_OBJECT_ITEM( it->data )){
 				subitems = na_object_get_items( it->data );
-				do_insert_items( treeview, model, subitems, newpath, level+1, parents );
+				do_insert_items( treeview, model, subitems, inserted_path, level+1, parents );
 				na_object_free_items( subitems );
 			}
 
-			if( newpath ){
-				gtk_tree_path_free( newpath );
-			}
+			gtk_tree_path_free( inserted_path );
+			g_free( inserted_path_str );
 		}
 	}
 
@@ -1185,6 +1198,40 @@ iter_on_selection( NactIActionsList *instance, FnIterOnSelection fn_iter, gpoint
 	g_list_free( listrows );
 }
 
+static GtkTreePath *
+object_to_path( NactIActionsList *instance, NactTreeModel *model, NAObject *object )
+{
+	ObjectToPathIter *otp;
+	GtkTreePath *path = NULL;
+
+	otp = g_new0( ObjectToPathIter, 1 );
+	otp->object = object;
+	otp->found = FALSE;
+	otp->path = NULL;
+
+	nact_tree_model_iter( model, ( FnIterOnStore ) object_to_path_iter, otp );
+
+	if( otp->found ){
+		path = gtk_tree_path_copy( otp->path );
+		gtk_tree_path_free( otp->path );
+	}
+
+	g_free( otp );
+
+	return( path );
+}
+
+static gboolean
+object_to_path_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ObjectToPathIter *otp )
+{
+	if( object == otp->object ){
+		otp->found = TRUE;
+		otp->path = gtk_tree_path_copy( path );
+	}
+
+	return( otp->found );
+}
+
 static gboolean
 on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsList *instance )
 {
@@ -1254,20 +1301,22 @@ on_iactions_list_item_updated( NactIActionsList *instance, NAObject *object )
 static void
 on_iactions_list_item_updated_treeview( NactIActionsList *instance, NAObject *object )
 {
-	NAObject *item;
+	NAObjectAction *item;
 	GtkTreeView *treeview;
 	GtkTreeModel *model;
 
 	if( object ){
-		item = NA_IS_OBJECT_PROFILE( object )
-			? NA_OBJECT( na_object_profile_get_action( NA_OBJECT_PROFILE( object )))
-			: object;
-
-		na_object_check_edition_status( item );
-
 		treeview = get_actions_list_treeview( instance );
 		model = gtk_tree_view_get_model( treeview );
+
+		na_object_check_edition_status( object );
 		nact_tree_model_display( NACT_TREE_MODEL( model ), object );
+
+		if( NA_IS_OBJECT_PROFILE( object )){
+			item = na_object_profile_get_action( NA_OBJECT_PROFILE( object ));
+			na_object_check_edition_status( item );
+			nact_tree_model_display( NACT_TREE_MODEL( model ), NA_OBJECT( item ));
+		}
 	}
 }
 
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index 22543a2..7a57eb4 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -322,6 +322,7 @@ on_new_profile_activated( GtkAction *gtk_action, NactMainWindow *window )
 	/*na_object_action_attach_profile( action, profile );*/
 	na_object_profile_set_action( profile, action );
 	na_object_set_id( profile, name );
+	na_object_check_edition_status( profile );
 
 	items = g_list_prepend( NULL, profile );
 	nact_iactions_list_insert_items( NACT_IACTIONS_LIST( window ), items, NULL );
@@ -380,24 +381,33 @@ static void
 save_object_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *object )
 {
 	GList *items, *it;
+	NAObjectItem *origin;
+	NAObjectItem *dup_pivot;
 
 	if( na_object_is_modified( NA_OBJECT( object )) &&
 		na_object_is_valid( NA_OBJECT( object )) &&
 		nact_window_save_item( NACT_WINDOW( window ), object )){
 
-			NAObjectItem *origin = NA_OBJECT_ITEM( na_object_get_origin( NA_OBJECT( object )));
+			g_debug( "save_object_item: about to get origin" );
+			/* do not use OA_OBJECT_ITEM macro as this may return a (valid)
+			 * NULL value
+			 */
+			origin = ( NAObjectItem * ) na_object_get_origin( object );
 
 			if( origin ){
-				na_object_copy( NA_OBJECT( origin ), NA_OBJECT( object ));
+				g_debug( "save_object_item: about to copy to origin" );
+				na_object_copy( origin, object );
 
 			} else {
-				NAObjectItem *dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( NA_OBJECT( object )));
-				na_object_set_origin( NA_OBJECT( dup_pivot ), NULL );
-				na_object_set_origin( NA_OBJECT( object ), NA_OBJECT( dup_pivot ));
+				g_debug( "save_object_item: about to duplicate" );
+				dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( object ));
+				na_object_set_origin( dup_pivot, NULL );
+				na_object_set_origin( object, dup_pivot );
 				na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
 			}
 
-			na_object_check_edition_status( NA_OBJECT( object ));
+			g_debug( "save_object_item: about to check edition status" );
+			na_object_check_edition_status( object );
 	}
 
 	/* Profiles are saved with their actions
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index 8992695..d86f935 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -620,11 +620,13 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
  * @object: a #NAObject-derived object to be inserted.
  * @path: the #GtkTreePath of the beginning of the current selection,
  * or NULL.
- * @iter: set to the new row
  * @obj_parent: set to the parent or the object itself.
  *
  * Insert a new row at the given position.
  *
+ * Returns: the path string of the inserted row as a newly allocated
+ * string. The returned path should be g_free() by the caller.
+ *
  * +--------------------+----------------------+----------------------+----------------------+
  * | inserted object -> |        action        |        profile       |         menu         |
  * +--------------------+----------------------+----------------------+----------------------+
@@ -643,9 +645,13 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
  * insert_before       : parent=NULL     , sibling_from_path (or null if path was null)
  * insert_before_parent: parent=NULL     , sibling_from_parent_path
  * insert_as_last_child: parent_from_path, sibling=NULL
+ *
+ * Gtk API uses to returns iter ; but at least when inserting a new profile in an action, we
+ * may have store_iter_path="0:1" (good), but iter_path="0:0" (bad) - so we return rather a
+ * string path
  */
-void
-nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, GtkTreeIter *iter, NAObject **obj_parent )
+gchar *
+nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **obj_parent )
 {
 	static const gchar *thisfn = "nact_tree_model_insert";
 	gchar *path_str;
@@ -659,16 +665,14 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
 	gboolean has_sibling_iter;
 
 	path_str = path ? gtk_tree_path_to_string( path ) : NULL;
-	g_debug( "%s: model=%p, object=%p (%s), path=%p (%s), iter=%p",
+	g_debug( "%s: model=%p, object=%p (%s), path=%p (%s)",
 			thisfn, ( void * ) model,
 			( void * ) object, G_OBJECT_TYPE_NAME( object ),
-			( void * ) path, path_str,
-			( void * ) iter );
+			( void * ) path, path_str );
 	g_free( path_str );
 
-	g_return_if_fail( NACT_IS_TREE_MODEL( model ));
-	g_return_if_fail( NA_IS_OBJECT( object ));
-	g_return_if_fail( iter );
+	g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), NULL );
+	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
 
 	store = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ));
 	has_parent_iter = FALSE;
@@ -679,8 +683,8 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
 		gtk_tree_model_get_iter( GTK_TREE_MODEL( model ), &select_iter, path );
 		gtk_tree_model_get( GTK_TREE_MODEL( model ), &select_iter, IACTIONS_LIST_NAOBJECT_COLUMN, &select_object, -1 );
 
-		g_return_if_fail( select_object );
-		g_return_if_fail( NA_IS_OBJECT( select_object ));
+		g_return_val_if_fail( select_object, NULL );
+		g_return_val_if_fail( NA_IS_OBJECT( select_object ), NULL );
 
 		if( NA_IS_OBJECT_ACTION( object )){
 			insert_get_iters_action( GTK_TREE_MODEL( store ), select_object, path, object, &parent_iter, &has_parent_iter, &sibling_iter, &has_sibling_iter, obj_parent );
@@ -697,14 +701,14 @@ nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePat
 		g_object_unref( select_object );
 
 	} else {
-		g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+		g_return_val_if_fail( NA_IS_OBJECT_ITEM( object ), NULL );
 	}
 
 	gtk_tree_store_insert_before( GTK_TREE_STORE( store ), &store_iter, has_parent_iter ? &parent_iter : NULL, has_sibling_iter ? &sibling_iter : NULL );
 	gtk_tree_store_set( GTK_TREE_STORE( store ), &store_iter, IACTIONS_LIST_NAOBJECT_COLUMN, object, -1 );
 	display_item( GTK_TREE_STORE( store ), model->private->treeview, &store_iter, object );
 
-	gtk_tree_model_filter_convert_child_iter_to_iter( GTK_TREE_MODEL_FILTER( model ), iter, &store_iter );
+	return( gtk_tree_model_get_string_from_iter( store, &store_iter ));
 }
 
 static void
diff --git a/src/nact/nact-tree-model.h b/src/nact/nact-tree-model.h
index 82c8f41..5cf9522 100644
--- a/src/nact/nact-tree-model.h
+++ b/src/nact/nact-tree-model.h
@@ -94,7 +94,7 @@ void    nact_tree_model_dispose( NactTreeModel *model );
 void    nact_tree_model_display( NactTreeModel *model, NAObject *object );
 void    nact_tree_model_dump( NactTreeModel *model );
 void    nact_tree_model_fill( NactTreeModel *model, GList *items, gboolean only_actions);
-void    nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, GtkTreeIter *iter, NAObject **parent );
+gchar  *nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent );
 void    nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data );
 void    nact_tree_model_remove( NactTreeModel *model, GList *selected );
 



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