[nautilus-actions] New NactTreeView convenience class



commit f44954e16baf30056c8b1862c200c8916cae43c7
Author: Pierre <pierre vfedora13 virtuals pwi>
Date:   Thu Feb 3 15:23:01 2011 +0100

    New NactTreeView convenience class

 ChangeLog                          |   76 +++
 po/POTFILES.in                     |    6 +-
 src/api/na-object-api.h            |    4 +-
 src/api/na-object-item.h           |    6 +-
 src/core/na-io-provider.c          |    2 +-
 src/core/na-object-item.c          |   43 +-
 src/core/na-object.c               |   97 ++--
 src/core/na-pivot.c                |   14 +-
 src/nact/Makefile.am               |    2 +
 src/nact/nact-assistant-export.c   |  188 ++-----
 src/nact/nact-assistant-import.c   |    2 +-
 src/nact/nact-iactions-list-bis.c  |    2 +-
 src/nact/nact-iactions-list-priv.c |   12 +
 src/nact/nact-iactions-list.c      |    2 +-
 src/nact/nact-iactions-list.h      |    5 +
 src/nact/nact-main-window.c        |   33 +-
 src/nact/nact-main-window.h        |    1 +
 src/nact/nact-marshal.def          |    3 +
 src/nact/nact-menubar-edit.c       |   14 +-
 src/nact/nact-menubar-file.c       |    6 +-
 src/nact/nact-menubar-maintainer.c |    2 +-
 src/nact/nact-menubar.c            |   25 +-
 src/nact/nact-tree-model-dnd.c     |    2 +-
 src/nact/nact-tree-model.c         |   57 ++-
 src/nact/nact-tree-model.h         |    1 +
 src/nact/nact-tree-view.c          | 1072 ++++++++++++++++++++++++++++++++++++
 src/nact/nact-tree-view.h          |  117 ++++
 src/plugin-menu/nautilus-actions.c |    2 +-
 28 files changed, 1509 insertions(+), 287 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 20b067a..2d7b339 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,81 @@
 2011-02-02 Pierre Wieser <pwieser trychlos org>
 
+	* src/nact/nact-tree-model.c:
+	* src/nact/nact-tree-model.h (nact_tree_model_get_items):
+	* src/nact/nact-tree-view.c:
+	* src/nact/nact-tree-view.h (nact_tree_view_get_items): New functions.
+
+	Allow an items list to be referenced in a new list.
+
+	* src/api/na-object-api.h (na_object_ref_items): New macro.
+
+	* src/api/na-object-item.h:
+	* src/core/na-object-item.c (na_object_item_ref_items): New function.
+
+	* src/nact/nact-assistant-export.c
+	(instance_dispose, on_tree_view_selection_changed): Updated accordingly.
+
+	Review NAObject reference management
+
+	* src/api/na-object-api.h
+	(na_object_unref_items, na_object_unref_items_rec): Removed macros.
+	(na_object_free_items): New macro.
+
+	* src/api/na-object-item.h:
+	* src/core/na-object-item.c
+	(na_object_item_unref_items, na_object_item_unref_items_rec): Removed functions.
+	(na_object_item_free_items): New function.
+
+	* src/core/na-io-provider.c (na_io_provider_load_items):
+	* src/core/na-object.c (na_object_object_ref, na_object_object_unref):
+	* src/core/na-pivot.c (instance_dispose, na_pivot_load_items,
+	na_pivot_set_new_items):
+	* src/nact/nact-assistant-import.c (assistant_apply):
+	* src/nact/nact-iactions-list-bis.c (nact_iactions_list_bis_get_items):
+	* src/nact/nact-iactions-list.c (free_items_callback):
+	* src/nact/nact-main-menubar-edit.c (nact_main_menubar_edit_on_cut,
+	nact_main_menubar_edit_on_copy, nact_main_menubar_edit_on_paste,
+	nact_main_menubar_edit_on_paste_into,
+	nact_main_menubar_edit_on_duplicate, nact_main_menubar_edit_on_delete):
+	* src/nact/nact-main-menubar-file.c
+	(nact_main_menubar_file_on_new_menu,
+	nact_main_menubar_file_on_new_action,
+	nact_main_menubar_file_on_new_profile):
+	* src/nact/nact-main-menubar-maintainer.c
+	(nact_main_menubar_maintainer_on_dump_selection):
+	* src/nact/nact-main-menubar.c (on_update_sensitivities):
+	* src/nact/nact-main-window.c (instance_dispose,
+	nact_main_window_remove_deleted, reload):
+	* src/nact/nact-tree-model-dnd.c (drop_uri_list):
+	* src/nact/nact-tree-model.c (fill_tree_store):
+	* src/nact/nact-tree-view.c (on_selection_changed_cleanup_handler):
+	* src/plugin-menu/nautilus-actions.c (get_menus_items): Updated
+	accordingl
+	* src/nact/nact-main-menubar-maintainer.c
+	(nact_main_menubar_maintainer_on_dump_selection):
+	* src/nact/nact-main-menubar.c (on_update_sensitivities):
+	* src/nact/nact-main-window.c (instance_dispose,
+	nact_main_window_remove_deleted, reload):
+	* src/nact/nact-tree-model-dnd.c (drop_uri_list):
+	* src/nact/nact-tree-model.c (fill_tree_store):
+	* src/nact/nact-tree-view.c (on_selection_changed_cleanup_handler):
+	* src/plugin-menu/nautilus-actions.c (get_menus_items):
+	Updated accordingly.
+
+	New NactTreeView convenience class
+
+	* src/nact/nact-tree-view.c:
+	* src/nact/nact-tree-view.h: New files.
+
+	* src/nact/Makefile.am:
+	* src/nact/nact-assistant-export.c:
+	* src/nact/nact-iactions-list-priv.c:
+	* src/nact/nact-iactions-list.h:
+	* src/nact/nact-marshal.list:
+	* src/nact/nact-tree-model.c: Updated accordingly.
+
+2011-02-02 Pierre Wieser <pwieser trychlos org>
+
 	Refactoring of menubar files:
 	- nact-main-menubar-*.c are renamed as nact-menubar-*.c.
 	- nact-main-menubar-*.h are removed.
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9d7a1d4..b3e44c5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -45,11 +45,11 @@ src/nact/nact-ifolders-tab.c
 src/nact/nact-imimetypes-tab.c
 src/nact/nact-iproperties-tab.c
 src/nact/nact-ischemes-tab.c
-src/nact/nact-main-menubar.c
-src/nact/nact-main-menubar-edit.c
-src/nact/nact-main-menubar-file.c
 src/nact/nact-main-window.c
 src/nact/nact-match-list.c
+src/nact/nact-menubar.c
+src/nact/nact-menubar-edit.c
+src/nact/nact-menubar-file.c
 [type: gettext/glade] src/nact/nact-preferences.ui
 src/nact/nact-providers-list.c
 src/nact/nact-schemes-list.c
diff --git a/src/api/na-object-api.h b/src/api/na-object-api.h
index 1c3e3c3..becbd26 100644
--- a/src/api/na-object-api.h
+++ b/src/api/na-object-api.h
@@ -132,8 +132,8 @@ 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_selected_items( tree )          na_object_item_unref_items_rec( tree )
+#define na_object_copyref_items( tree )                 na_object_item_copyref_items( tree )
+#define na_object_free_items( tree )                    na_object_item_free_items( tree )
 
 #define na_object_is_finally_writable( obj, r )			na_object_item_is_finally_writable( NA_OBJECT_ITEM( obj ), ( r ))
 #define na_object_set_writability_status( obj, w, r )	na_object_item_set_writability_status( NA_OBJECT_ITEM( obj ), ( w ), ( r ))
diff --git a/src/api/na-object-item.h b/src/api/na-object-item.h
index 495991f..fd125a0 100644
--- a/src/api/na-object-item.h
+++ b/src/api/na-object-item.h
@@ -103,9 +103,9 @@ void        na_object_item_remove_item ( NAObjectItem *item, const NAObjectId *c
 
 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_count_items  ( GList *items, gint *menus, gint *actions, gint *profiles, gboolean recurse );
+GList      *na_object_item_copyref_items( GList *items );
+GList      *na_object_item_free_items   ( GList *items );
 
 void        na_object_item_deals_with_version    ( NAObjectItem *item );
 void        na_object_item_rebuild_children_slist( NAObjectItem *item );
diff --git a/src/core/na-io-provider.c b/src/core/na-io-provider.c
index b107f12..fcbb37b 100644
--- a/src/core/na-io-provider.c
+++ b/src/core/na-io-provider.c
@@ -621,7 +621,7 @@ na_io_provider_is_finally_writable( const NAIOProvider *provider, guint *reason
  * in display order. This tree contains #NAObjectMenu menus, along with
  * #NAObjectAction actions and their #NAObjectProfile profiles.
  *
- * The returned list should be na_object_unref_items() by the caller.
+ * The returned list should be na_object_free_items().
  */
 GList *
 na_io_provider_load_items( const NAPivot *pivot, guint loadable_set, GSList **messages )
diff --git a/src/core/na-object-item.c b/src/core/na-object-item.c
index 5b365bd..e9dc935 100644
--- a/src/core/na-object-item.c
+++ b/src/core/na-object-item.c
@@ -164,7 +164,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
 static void
 instance_dispose( GObject *object )
 {
-	static const gchar *thisfn = "na_object_item_instance_dispose";
 	NAObjectItem *self;
 	GList *children;
 
@@ -177,9 +176,8 @@ instance_dispose( GObject *object )
 		self->private->dispose_has_run = TRUE;
 
 		children = na_object_get_items( self );
-		g_debug( "%s: children=%p (count=%d)", thisfn, ( void * ) children, g_list_length( children ));
 		na_object_set_items( self, NULL );
-		na_object_unref_items( children );
+		na_object_free_items( children );
 
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
@@ -708,42 +706,41 @@ na_object_item_count_items( GList *items, gint *menus, gint *actions, gint *prof
 }
 
 /**
- * na_object_item_unref_items:
+ * na_object_item_copyref_items:
  * @items: a list of #NAObject -derived items.
  *
- * Unref only the first level the #NAObject of the list, freeing the list at last.
+ * Creates a copy of the provided list, recursively incrementing the
+ * reference count of NAObjects.
  *
- * This is rather only used by NAPivot.
+ * Returns: the new list, which should be na_object_free_items() by the
+ * caller.
  *
- * Since: 2.30
+ * Since: 3.1.0
  */
-void
-na_object_item_unref_items( GList *items )
+GList *
+na_object_item_copyref_items( GList *items )
 {
-	g_list_foreach( items, ( GFunc ) g_object_unref, NULL );
-	g_list_free( items );
+	GList *copy = g_list_copy( items );
+	g_list_foreach( copy, ( GFunc ) na_object_object_ref, NULL );
+	return( copy );
 }
 
 /**
- * na_object_item_unref_items_rec:
+ * na_object_item_free_items:
  * @items: a list of #NAObject -derived items.
  *
- * Recursively unref the #NAObject's of the list, freeing the list at last.
+ * Free the items list.
  *
- * This is heavily used by NACT.
+ * Returns: a %NULL pointer.
  *
- * Since: 2.30
+ * Since: 3.1.0
  */
-void
-na_object_item_unref_items_rec( GList *items )
+GList *
+na_object_item_free_items( GList *items )
 {
-	GList *it;
-
-	for( it = items ; it ; it = it->next ){
-		na_object_unref( it->data );
-	}
-
+	g_list_foreach( items, ( GFunc ) na_object_object_unref, NULL );
 	g_list_free( items );
+	return( NULL );
 }
 
 /**
diff --git a/src/core/na-object.c b/src/core/na-object.c
index 5c73b11..ee29d07 100644
--- a/src/core/na-object.c
+++ b/src/core/na-object.c
@@ -68,27 +68,27 @@ typedef gboolean ( *HierarchyIterFunc )( GObjectClass *class, const NAObject *ob
 
 static GObjectClass *st_parent_class   = NULL;
 
-static GType          register_type( void );
-static void           class_init( NAObjectClass *klass );
-static void           instance_init( GTypeInstance *instance, gpointer klass );
-static void           instance_dispose( GObject *object );
-static void           instance_finalize( GObject *object );
-
-static void           object_dump( const NAObject *object );
-
-static void           iduplicable_iface_init( NAIDuplicableInterface *iface );
-static void           iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *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 void           push_modified_status_up( const NAObject *object, gboolean is_modified );
-static gboolean       object_copy_iter( GObjectClass *class, const NAObject *source, CopyIter *data );
-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 );
-static GList         *build_class_hierarchy( const NAObject *object );
+static GType    register_type( void );
+static void     class_init( NAObjectClass *klass );
+static void     instance_init( GTypeInstance *instance, gpointer klass );
+static void     instance_dispose( GObject *object );
+static void     instance_finalize( GObject *object );
+
+static void     object_dump( const NAObject *object );
+
+static void     iduplicable_iface_init( NAIDuplicableInterface *iface );
+static void     iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *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 void     push_modified_status_up( const NAObject *object, gboolean is_modified );
+static gboolean object_copy_iter( GObjectClass *class, const NAObject *source, CopyIter *data );
+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 );
+static GList   *build_class_hierarchy( const NAObject *object );
 
 GType
 na_object_object_get_type( void )
@@ -609,8 +609,8 @@ dump_tree( GList *tree, gint level )
 {
 	GString *prefix;
 	gint i;
-	GList *subitems, *it;
-	gchar *id;
+	GList *it;
+	const NAObject *object;
 	gchar *label;
 
 	prefix = g_string_new( "" );
@@ -619,16 +619,14 @@ dump_tree( GList *tree, gint level )
 	}
 
 	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 );
+		object = ( const NAObject * ) it->data;
+		label = na_object_get_label( object );
+		g_debug( "na_object_dump_tree: %s%p (%s, ref_count=%u) '%s'", prefix->str,
+				( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count, label );
 		g_free( label );
 
-		if( NA_IS_OBJECT_ITEM( it->data )){
-			subitems = na_object_get_items( it->data );
-			dump_tree( subitems, level+1 );
+		if( NA_IS_OBJECT_ITEM( object )){
+			dump_tree( na_object_get_items( object ), level+1 );
 		}
 	}
 
@@ -680,34 +678,23 @@ na_object_object_reset_origin( NAObject *object, const NAObject *origin )
  * Recursively ref the @object and all its children, incrementing their
  * reference_count by 1.
  *
- * Returns: a reference on the @pbject.
+ * Returns: a reference on the @object.
  *
  * Since: 2.30
  */
 NAObject *
 na_object_object_ref( NAObject *object )
 {
-	NAObject *ref = NULL;
-	GList *children, *ic;
+	NAObject *ref;
 
 	g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
 
-	if( !object->private->dispose_has_run ){
+	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 );
+	if( !object->private->dispose_has_run ){
 
 		if( NA_IS_OBJECT_ITEM( object )){
-
-			children = na_object_get_items( object );
-
-			for( ic = children ; ic ; ic = ic->next ){
-				/*
-				g_debug( "na_object_object_ref: child=%p (%s, ref_count=%d)",
-							( void * ) ic->data, G_OBJECT_TYPE_NAME( ic->data ), G_OBJECT( ic->data )->ref_count );
-							*/
-				na_object_ref( ic->data );
-			}
+			g_list_foreach( na_object_get_items( object ), ( GFunc ) na_object_object_ref, NULL );
 		}
 
 		ref = g_object_ref( object );
@@ -728,28 +715,14 @@ na_object_object_ref( NAObject *object )
 void
 na_object_object_unref( NAObject *object )
 {
-	GList *children;
-	GList *ic, *icnext;
-
 	g_return_if_fail( NA_IS_OBJECT( object ));
 
 	if( !object->private->dispose_has_run ){
 
-		g_debug( "na_object_object_unref: object=%p (%s, ref_count=%d)",
-				( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
-
 		if( NA_IS_OBJECT_ITEM( object )){
-			children = na_object_get_items( object );
-
-			for( ic = children ; ic ; ic = icnext ){
-				icnext = ic->next;
-				g_object_unref( ic->data );
-			}
+			g_list_foreach( na_object_get_items( object ), ( GFunc ) na_object_object_unref, NULL );
 		}
 
-		/*g_debug( "na_object_object_unref:about_to_unref: object=%p (%s, ref_count=%d)",
-				( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );*/
-
 		g_object_unref( object );
 	}
 }
diff --git a/src/core/na-pivot.c b/src/core/na-pivot.c
index 64f4685..bb94e0f 100644
--- a/src/core/na-pivot.c
+++ b/src/core/na-pivot.c
@@ -308,9 +308,10 @@ instance_dispose( GObject *object )
 		self->private->modules = NULL;
 
 		/* release item tree */
-		g_debug( "%s: tree=%p, count=%u", thisfn, ( void * ) self->private->tree, g_list_length( self->private->tree ));
-		na_object_unref_items( self->private->tree );
-		self->private->tree = NULL;
+		g_debug( "%s: tree=%p (count=%u)", thisfn,
+				( void * ) self->private->tree, g_list_length( self->private->tree ));
+		na_object_dump_tree( self->private->tree );
+		self->private->tree = na_object_free_items( self->private->tree );
 
 		/* release the settings */
 		g_object_unref( self->private->settings );
@@ -553,7 +554,7 @@ na_pivot_load_items( NAPivot *pivot )
 		g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
 
 		messages = NULL;
-		na_object_unref_items( pivot->private->tree );
+		na_object_free_items( pivot->private->tree );
 		pivot->private->tree = na_io_provider_load_items( pivot, pivot->private->loadable_set, &messages );
 
 		for( im = messages ; im ; im = im->next ){
@@ -569,7 +570,8 @@ na_pivot_load_items( NAPivot *pivot )
  * @pivot: this #NAPivot instance.
  * @tree: the new tree of items.
  *
- * Replace the current list with this one.
+ * Replace the current list with this one, acquiring the full ownership
+ * of the provided @tree.
  */
 void
 na_pivot_set_new_items( NAPivot *pivot, GList *items )
@@ -583,7 +585,7 @@ na_pivot_set_new_items( NAPivot *pivot, GList *items )
 		g_debug( "%s: pivot=%p, items=%p (count=%d)",
 				thisfn, ( void * ) pivot, ( void * ) items, items ? g_list_length( items ) : 0 );
 
-		na_object_unref_items( pivot->private->tree );
+		na_object_free_items( pivot->private->tree );
 		pivot->private->tree = items;
 	}
 }
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index 9d77dc8..446b7de 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -147,6 +147,8 @@ nautilus_actions_config_tool_SOURCES = \
 	nact-tree-model-dnd.c								\
 	nact-tree-model-dnd.h								\
 	nact-tree-model-priv.h								\
+	nact-tree-view.c									\
+	nact-tree-view.h									\
 	nact-window.c										\
 	nact-window.h										\
 	$(BUILT_SOURCES)									\
diff --git a/src/nact/nact-assistant-export.c b/src/nact/nact-assistant-export.c
index 880b200..2fb2e98 100644
--- a/src/nact/nact-assistant-export.c
+++ b/src/nact/nact-assistant-export.c
@@ -46,7 +46,7 @@
 #include "nact-assistant-export.h"
 #include "nact-export-ask.h"
 #include "nact-export-format.h"
-#include "nact-iactions-list.h"
+#include "nact-tree-view.h"
 
 /* Export Assistant
  *
@@ -78,10 +78,12 @@ struct _NactAssistantExportClassPrivate {
 /* private instance data
  */
 struct _NactAssistantExportPrivate {
-	gboolean  dispose_has_run;
-	gboolean  preferences_locked;
-	gchar    *uri;
-	GList    *results;
+	gboolean      dispose_has_run;
+	NactTreeView *items_view;
+	gboolean      preferences_locked;
+	gchar        *uri;
+	GList        *selected_items;
+	GList        *results;
 };
 
 typedef struct {
@@ -100,23 +102,18 @@ static BaseAssistantClass *st_parent_class   = NULL;
 
 static GType           register_type( void );
 static void            class_init( NactAssistantExportClass *klass );
-static void            iactions_list_iface_init( NactIActionsListInterface *iface );
 static void            instance_init( GTypeInstance *instance, gpointer klass );
 static void            instance_dispose( GObject *application );
 static void            instance_finalize( GObject *application );
 
-static void            on_base_initialize_gtk_toplevel( NactAssistantExport *dialog, GtkAssistant *toplevel );
-static void            on_base_initialize_base_window( NactAssistantExport *dialog );
-static void            on_base_all_widgets_showed( NactAssistantExport *dialog );
+static void            on_base_initialize_gtk_toplevel( NactAssistantExport *dialog, GtkAssistant *toplevel, gpointer user_data );
+static void            on_base_initialize_base_window( NactAssistantExport *dialog, gpointer user_data );
+static void            on_base_all_widgets_showed( NactAssistantExport *dialog, gpointer user_data );
 
-static void            assist_initial_load_intro( NactAssistantExport *window, GtkAssistant *assistant );
 static void            assist_runtime_init_intro( NactAssistantExport *window, GtkAssistant *assistant );
 
-static void            assist_initial_load_actions_list( NactAssistantExport *window, GtkAssistant *assistant );
 static void            assist_runtime_init_actions_list( NactAssistantExport *window, GtkAssistant *assistant );
-static void            on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
-static gchar          *on_iactions_list_get_treeview_name( NactIActionsList *instance );
-
+static void            on_tree_view_selection_changed( NactAssistantExport *window, NactTreeView *view, GList *selected_items, gpointer user_data );
 static void            assist_initial_load_target_folder( NactAssistantExport *window, GtkAssistant *assistant );
 static void            assist_runtime_init_target_folder( NactAssistantExport *window, GtkAssistant *assistant );
 static GtkFileChooser *get_folder_chooser( NactAssistantExport *window );
@@ -126,12 +123,6 @@ static void            assist_initial_load_format( NactAssistantExport *window,
 static void            assist_runtime_init_format( NactAssistantExport *window, GtkAssistant *assistant );
 static NAExportFormat *get_export_format( NactAssistantExport *window );
 
-static void            assist_initial_load_confirm( NactAssistantExport *window, GtkAssistant *assistant );
-static void            assist_runtime_init_confirm( NactAssistantExport *window, GtkAssistant *assistant );
-
-static void            assist_initial_load_exportdone( NactAssistantExport *window, GtkAssistant *assistant );
-static void            assist_runtime_init_exportdone( NactAssistantExport *window, GtkAssistant *assistant );
-
 static void            assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page );
 static void            assist_prepare_confirm( NactAssistantExport *window, GtkAssistant *assistant, GtkWidget *page );
 static void            assistant_apply( BaseAssistant *window, GtkAssistant *assistant );
@@ -168,18 +159,10 @@ register_type( void )
 		( GInstanceInitFunc ) instance_init
 	};
 
-	static const GInterfaceInfo iactions_list_iface_info = {
-		( GInterfaceInitFunc ) iactions_list_iface_init,
-		NULL,
-		NULL
-	};
-
 	g_debug( "%s", thisfn );
 
 	type = g_type_register_static( BASE_ASSISTANT_TYPE, "NactAssistantExport", &info, 0 );
 
-	g_type_add_interface_static( type, NACT_IACTIONS_LIST_TYPE, &iactions_list_iface_info );
-
 	return( type );
 }
 
@@ -206,16 +189,6 @@ class_init( NactAssistantExportClass *klass )
 }
 
 static void
-iactions_list_iface_init( NactIActionsListInterface *iface )
-{
-	static const gchar *thisfn = "nact_assistant_export_iactions_list_iface_init";
-
-	g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
-	iface->get_treeview_name = on_iactions_list_get_treeview_name;
-}
-
-static void
 instance_init( GTypeInstance *instance, gpointer klass )
 {
 	static const gchar *thisfn = "nact_assistant_export_instance_init";
@@ -257,7 +230,9 @@ instance_dispose( GObject *window )
 
 		self->private->dispose_has_run = TRUE;
 
-		nact_iactions_list_dispose( NACT_IACTIONS_LIST( window ));
+		if( self->private->selected_items ){
+			self->private->selected_items = na_object_free_items( self->private->selected_items );
+		}
 
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
@@ -321,11 +296,13 @@ nact_assistant_export_run( BaseWindow *main_window )
 			BASE_PROP_WARN_ON_ESCAPE,  esc_confirm,
 			NULL );
 
+	assistant->private->items_view = nact_tree_view_new( BASE_WINDOW( assistant ), "ActionsList" );
+
 	base_window_run( BASE_WINDOW( assistant ));
 }
 
 static void
-on_base_initialize_gtk_toplevel( NactAssistantExport *dialog, GtkAssistant *assistant )
+on_base_initialize_gtk_toplevel( NactAssistantExport *dialog, GtkAssistant *assistant, gpointer user_data )
 {
 	static const gchar *thisfn = "nact_assistant_export_on_base_initialize_gtk_toplevel";
 	NactApplication *application;
@@ -336,7 +313,8 @@ on_base_initialize_gtk_toplevel( NactAssistantExport *dialog, GtkAssistant *assi
 	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT( dialog ));
 
 	if( !dialog->private->dispose_has_run ){
-		g_debug( "%s: dialog=%p, assistant=%p", thisfn, ( void * ) dialog, ( void * ) assistant );
+		g_debug( "%s: dialog=%p, assistant=%p, user_data=%p",
+				thisfn, ( void * ) dialog, ( void * ) assistant, ( void * ) user_data );
 
 		application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( dialog )));
 		updater = nact_application_get_updater( application );
@@ -345,17 +323,13 @@ on_base_initialize_gtk_toplevel( NactAssistantExport *dialog, GtkAssistant *assi
 		are_locked = na_settings_get_boolean( settings, NA_IPREFS_ADMIN_PREFERENCES_LOCKED, NULL, &mandatory );
 		dialog->private->preferences_locked = are_locked && mandatory;
 
-		assist_initial_load_intro( dialog, assistant );
-		assist_initial_load_actions_list( dialog, assistant );
 		assist_initial_load_target_folder( dialog, assistant );
 		assist_initial_load_format( dialog, assistant );
-		assist_initial_load_confirm( dialog, assistant );
-		assist_initial_load_exportdone( dialog, assistant );
 	}
 }
 
 static void
-on_base_initialize_base_window( NactAssistantExport *dialog )
+on_base_initialize_base_window( NactAssistantExport *dialog, gpointer user_data )
 {
 	static const gchar *thisfn = "nact_assistant_export_on_base_initialize_base_window";
 	GtkAssistant *assistant;
@@ -363,42 +337,42 @@ on_base_initialize_base_window( NactAssistantExport *dialog )
 	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT( dialog ));
 
 	if( !dialog->private->dispose_has_run ){
-		g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+		g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) dialog, ( void * ) user_data );
 
 		assistant = GTK_ASSISTANT( base_window_get_gtk_toplevel( BASE_WINDOW( dialog )));
 
 		base_window_signal_connect( BASE_WINDOW( dialog ),
-				G_OBJECT( dialog ), IACTIONS_LIST_SIGNAL_SELECTION_CHANGED, G_CALLBACK( on_iactions_list_selection_changed ));
+				G_OBJECT( dialog ), TREE_SIGNAL_SELECTION_CHANGED, G_CALLBACK( on_tree_view_selection_changed ));
 
 		assist_runtime_init_intro( dialog, assistant );
 		assist_runtime_init_actions_list( dialog, assistant );
 		assist_runtime_init_target_folder( dialog, assistant );
 		assist_runtime_init_format( dialog, assistant );
-		assist_runtime_init_confirm( dialog, assistant );
-		assist_runtime_init_exportdone( dialog, assistant );
 	}
 }
 
 static void
-on_base_all_widgets_showed( NactAssistantExport *dialog )
+on_base_all_widgets_showed( NactAssistantExport *dialog, gpointer user_data )
 {
 	static const gchar *thisfn = "nact_assistant_export_on_base_all_widgets_showed";
+	NactMainWindow *main_window;
+	GList *items;
 
 	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT( dialog ));
 
 	if( !dialog->private->dispose_has_run ){
-		g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
-
-		nact_iactions_list_bis_select_first_row( NACT_IACTIONS_LIST( dialog ));
+		g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) dialog, ( void * ) user_data );
+
+		/* setup the data here so that we are sure all companion objects
+		 * have connected their signal handlers
+		 */
+		main_window = NACT_MAIN_WINDOW( base_window_get_parent( BASE_WINDOW( dialog )));
+		items = nact_main_window_get_current_items( main_window );
+		nact_tree_view_fill( dialog->private->items_view, items );
 	}
 }
 
 static void
-assist_initial_load_intro( NactAssistantExport *window, GtkAssistant *assistant )
-{
-}
-
-static void
 assist_runtime_init_intro( NactAssistantExport *window, GtkAssistant *assistant )
 {
 	static const gchar *thisfn = "nact_assistant_export_runtime_init_intro";
@@ -411,71 +385,45 @@ assist_runtime_init_intro( NactAssistantExport *window, GtkAssistant *assistant
 }
 
 static void
-assist_initial_load_actions_list( NactAssistantExport *window, GtkAssistant *assistant )
-{
-	g_assert( NACT_IS_IACTIONS_LIST( window ));
-
-	nact_iactions_list_set_management_mode( NACT_IACTIONS_LIST( window ), IACTIONS_LIST_MANAGEMENT_MODE_EXPORT );
-	nact_iactions_list_initial_load_toplevel( NACT_IACTIONS_LIST( window ));
-}
-
-static void
 assist_runtime_init_actions_list( NactAssistantExport *window, GtkAssistant *assistant )
 {
-	BaseWindow *parent;
-	GList *tree;
 	GtkWidget *content;
 
-	parent = base_window_get_parent( BASE_WINDOW( window ));
-	g_assert( NACT_IS_MAIN_WINDOW( parent ));
-	g_assert( NACT_IS_IACTIONS_LIST( parent ));
-	tree = nact_iactions_list_bis_get_items( NACT_IACTIONS_LIST( parent ));
-
-	nact_iactions_list_runtime_init_toplevel( NACT_IACTIONS_LIST( window ), tree );
-
 	content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_ACTIONS_SELECTION );
-
 	gtk_assistant_set_page_complete( assistant, content, FALSE );
 }
 
 static void
-on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
+on_tree_view_selection_changed( NactAssistantExport *instance, NactTreeView *view, GList *selected_items, gpointer user_data )
 {
-	static const gchar *thisfn = "nact_assistant_export_on_actions_list_selection_changed";
-
-	g_debug( "%s: selection=%p, selected_items=%p (count=%d)",
-			thisfn, ( void * ) instance, ( void * ) selected_items, g_slist_length( selected_items ));
-
+	static const gchar *thisfn = "nact_assistant_export_on_tree_view_selection_changed";
 	GtkAssistant *assistant;
 	gint pos;
 	gboolean enabled;
 	GtkWidget *content;
 
-	g_assert( NACT_IS_ASSISTANT_EXPORT( instance ));
+	g_return_if_fail( NACT_IS_ASSISTANT_EXPORT( instance ));
+
+	g_debug( "%s: instance=%p, view=%p, selected_items=%p (count=%d), user_data=%p",
+			thisfn, ( void * ) instance, ( void * ) view,
+			( void * ) selected_items, g_list_length( selected_items ), ( void * ) user_data );
+
+	if( instance->private->selected_items ){
+		instance->private->selected_items = na_object_free_items( instance->private->selected_items );
+	}
+
 	assistant = GTK_ASSISTANT( base_window_get_gtk_toplevel( BASE_WINDOW( instance )));
 	pos = gtk_assistant_get_current_page( assistant );
-	if( pos == ASSIST_PAGE_ACTIONS_SELECTION ){
-
-		enabled = ( g_slist_length( selected_items ) > 0 );
 
+	if( pos == ASSIST_PAGE_ACTIONS_SELECTION ){
+		enabled = ( g_list_length( selected_items ) > 0 );
+		instance->private->selected_items = na_object_copyref_items( selected_items );
 		content = gtk_assistant_get_nth_page( assistant, pos );
 		gtk_assistant_set_page_complete( assistant, content, enabled );
 		gtk_assistant_update_buttons_state( assistant );
 	}
 }
 
-static gchar *
-on_iactions_list_get_treeview_name( NactIActionsList *instance )
-{
-	gchar *name = NULL;
-
-	g_return_val_if_fail( NACT_IS_ASSISTANT_EXPORT( instance ), NULL );
-
-	name = g_strdup( "ActionsList" );
-
-	return( name );
-}
-
 static void
 assist_initial_load_target_folder( NactAssistantExport *window, GtkAssistant *assistant )
 {
@@ -507,11 +455,8 @@ assist_runtime_init_target_folder( NactAssistantExport *window, GtkAssistant *as
 	}
 	g_free( uri );
 
-	base_window_signal_connect(
-			BASE_WINDOW( window ),
-			G_OBJECT( chooser ),
-			"selection-changed",
-			G_CALLBACK( on_folder_selection_changed ));
+	base_window_signal_connect( BASE_WINDOW( window ),
+			G_OBJECT( chooser ), "selection-changed", G_CALLBACK( on_folder_selection_changed ));
 
 	content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FOLDER_SELECTION );
 	gtk_assistant_set_page_complete( assistant, content, FALSE );
@@ -621,26 +566,6 @@ get_export_format( NactAssistantExport *window )
 }
 
 static void
-assist_initial_load_confirm( NactAssistantExport *window, GtkAssistant *assistant )
-{
-}
-
-static void
-assist_runtime_init_confirm( NactAssistantExport *window, GtkAssistant *assistant )
-{
-}
-
-static void
-assist_initial_load_exportdone( NactAssistantExport *window, GtkAssistant *assistant )
-{
-}
-
-static void
-assist_runtime_init_exportdone( NactAssistantExport *window, GtkAssistant *assistant )
-{
-}
-
-static void
 assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page )
 {
 	/*static const gchar *thisfn = "nact_assistant_export_on_prepare";
@@ -670,7 +595,7 @@ assist_prepare_confirm( NactAssistantExport *window, GtkAssistant *assistant, Gt
 	gchar *label_item;
 	gchar *label11, *label12;
 	gchar *label21, *label22;
-	GList *items, *it;
+	GList *it;
 	NAExportFormat *format;
 	GtkLabel *confirm_label;
 	NactApplication *application;
@@ -686,13 +611,11 @@ assist_prepare_confirm( NactAssistantExport *window, GtkAssistant *assistant, Gt
 	text = g_string_new( "" );
 	g_string_printf( text, "<b>%s</b>\n\n", _( "About to export selected items:" ));
 
-	items = nact_iactions_list_bis_get_selected_items( NACT_IACTIONS_LIST( window ));
-	for( it = items ; it ; it = it->next ){
+	for( it = window->private->selected_items ; it ; it = it->next ){
 		label_item = na_object_get_label( it->data );
 		g_string_append_printf( text, "\t%s\n", label_item );
 		g_free( label_item );
 	}
-	na_object_unref_selected_items( items );
 
 	g_assert( window->private->uri && strlen( window->private->uri ));
 
@@ -731,7 +654,7 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 {
 	static const gchar *thisfn = "nact_assistant_export_on_apply";
 	NactAssistantExport *window;
-	GList *actions, *ia;
+	GList *ia;
 	ExportStruct *str;
 	NactApplication *application;
 	NAUpdater *updater;
@@ -745,12 +668,11 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 
 	application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
 	updater = nact_application_get_updater( application );
-	actions = nact_iactions_list_bis_get_selected_items( NACT_IACTIONS_LIST( window ));
 	first = TRUE;
 
 	g_return_if_fail( window->private->uri && strlen( window->private->uri ));
 
-	for( ia = actions ; ia ; ia = ia->next ){
+	for( ia = window->private->selected_items ; ia ; ia = ia->next ){
 		str = g_new0( ExportStruct, 1 );
 		window->private->results = g_list_append( window->private->results, str );
 
@@ -772,8 +694,6 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 
 		first = FALSE;
 	}
-
-	na_object_unref_selected_items( actions );
 }
 
 static void
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index e092027..a76d34d 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -680,7 +680,7 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
 	 */
 	imported_items = g_list_reverse( imported_items );
 	nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( main_window ), imported_items, NULL );
-	na_object_unref_items( imported_items );
+	na_object_free_items( imported_items );
 }
 
 static NAObjectItem *
diff --git a/src/nact/nact-iactions-list-bis.c b/src/nact/nact-iactions-list-bis.c
index 776bebb..730b45f 100644
--- a/src/nact/nact-iactions-list-bis.c
+++ b/src/nact/nact-iactions-list-bis.c
@@ -341,7 +341,7 @@ nact_iactions_list_bis_get_items( NactIActionsList *instance )
  * We acquire here a new reference on objects corresponding to actually
  * selected rows, and their childs.
  *
- * The caller may safely call na_object_free_items_list() on the
+ * The caller may safely call na_object_free_items() on the
  * returned list.
  */
 GList *
diff --git a/src/nact/nact-iactions-list-priv.c b/src/nact/nact-iactions-list-priv.c
index dc63960..d300693 100644
--- a/src/nact/nact-iactions-list-priv.c
+++ b/src/nact/nact-iactions-list-priv.c
@@ -34,6 +34,7 @@
 
 #include "base-window.h"
 #include "nact-iactions-list-priv.h"
+#include "nact-tree-view.h"
 
 #define IACTIONS_LIST_DATA_INSTANCE		"nact-iactions-list-instance-data"
 
@@ -60,11 +61,17 @@ nact_iactions_list_priv_get_actions_list_treeview( NactIActionsList *instance )
  * @instance: this #NactIActionsList interface.
  *
  * Returns a pointer to the data associated to this instance of the interface.
+ *
+ * During the transition phase (refactoring of IActionsList interface to
+ * TreeView class), the function tests if a TreeView is defined in this
+ * instance. If yes, then it asks the object to fillup out structure with
+ * its own data.
  */
 IActionsListInstanceData *
 nact_iactions_list_priv_get_instance_data( NactIActionsList *instance )
 {
 	IActionsListInstanceData *ialid;
+	NactTreeView *view;
 
 	ialid = ( IActionsListInstanceData * ) g_object_get_data( G_OBJECT( instance ), IACTIONS_LIST_DATA_INSTANCE );
 
@@ -73,6 +80,11 @@ nact_iactions_list_priv_get_instance_data( NactIActionsList *instance )
 		g_object_set_data( G_OBJECT( instance ), IACTIONS_LIST_DATA_INSTANCE, ialid );
 	}
 
+	view = ( NactTreeView * ) g_object_get_data( G_OBJECT( instance ), "window-data-tree-view" );
+	if( view && NACT_IS_TREE_VIEW( view )){
+		nact_tree_view_setup_ialid( view, ialid );
+	}
+
 	return( ialid );
 }
 
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 69818d5..a5b11a9 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -291,7 +291,7 @@ free_items_callback( NactIActionsList *instance, GList *items )
 	g_debug( "nact_iactions_list_free_items_callback: selection=%p (%d items)",
 			( void * ) items, g_list_length( items ));
 
-	na_object_unref_selected_items( items );
+	na_object_free_items( items );
 }
 
 static void
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index 4ba4385..8904e3d 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -48,6 +48,11 @@
  *   refilled on demand.
  *   Counters are then incremented in nact_iactions_list_insert() and
  *   nact_iactions_list_delete() functions.
+ *
+ * As of 3.1.0, the IActionsList interface is going to be replaced
+ * by a NactItemsTreeView class, itself derived from NactTreeView.
+ * During the transition phase, the interface stays being initialized
+ * as well as the two classes are instanciated.
  */
 
 #include <gtk/gtk.h>
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index aad8615..479ff93 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -726,7 +726,7 @@ instance_dispose( GObject *window )
 		for( it = self->private->deleted ; it ; it = it->next ){
 			g_debug( "nact_main_window_instance_dispose: deleted=%p (%s)", ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ));
 		}
-		na_object_unref_items( self->private->deleted );
+		na_object_free_items( self->private->deleted );
 
 		nact_iactions_list_dispose( NACT_IACTIONS_LIST( window ));
 		nact_sort_buttons_dispose( self );
@@ -1108,8 +1108,7 @@ reload_items( NactMainWindow *window )
 	window->private->selected_item = NULL;
 	window->private->selected_profile = NULL;
 
-	na_object_unref_items( window->private->deleted );
-	window->private->deleted = NULL;
+	window->private->deleted = na_object_free_items( window->private->deleted );
 
 	tree = na_updater_load_items( window->private->updater );
 	nact_iactions_list_fill( NACT_IACTIONS_LIST( window ), tree );
@@ -1192,6 +1191,29 @@ on_delete_event( GtkWidget *toplevel, GdkEvent *event, NactMainWindow *window )
 }
 
 /**
+ * nact_main_window_get_current_items:
+ * @window: this #NactMainWindow instance.
+ *
+ * Returns: The current content of the items tree view.
+ */
+GList *
+nact_main_window_get_current_items( const NactMainWindow *window )
+{
+	GList *items;
+
+	g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), NULL );
+
+	items = NULL;
+
+	if( !window->private->dispose_has_run ){
+
+		items = nact_iactions_list_bis_get_items( NACT_IACTIONS_LIST( window ));
+	}
+
+	return( items );
+}
+
+/**
  * nact_main_window_has_modified_items:
  * @window: this #NactMainWindow instance.
  *
@@ -1303,14 +1325,13 @@ nact_main_window_remove_deleted( NactMainWindow *window, GSList **messages )
 			delete_ok = actually_delete_item( window, item, window->private->updater, &not_deleted, messages );
 		}
 
-		na_object_unref_items( window->private->deleted );
-		window->private->deleted = NULL;
+		window->private->deleted = na_object_free_items( window->private->deleted );
 
 		setup_dialog_title( window );
 
 		if( g_list_length( not_deleted )){
 			nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), not_deleted, NULL );
-			na_object_unref_items( not_deleted );
+			na_object_free_items( not_deleted );
 		}
 	}
 
diff --git a/src/nact/nact-main-window.h b/src/nact/nact-main-window.h
index 63f8696..e40c3f0 100644
--- a/src/nact/nact-main-window.h
+++ b/src/nact/nact-main-window.h
@@ -90,6 +90,7 @@ NactMainWindow *nact_main_window_new( const NactApplication *application );
 
 NactClipboard  *nact_main_window_get_clipboard     ( const NactMainWindow *window );
 NAObjectItem   *nact_main_window_get_item          ( const NactMainWindow *window, const gchar *id );
+GList          *nact_main_window_get_current_items ( const NactMainWindow *window );
 gboolean        nact_main_window_has_modified_items( const NactMainWindow *window );
 void            nact_main_window_move_to_deleted   ( NactMainWindow *window, GList *items );
 void            nact_main_window_reload            ( NactMainWindow *window );
diff --git a/src/nact/nact-marshal.def b/src/nact/nact-marshal.def
index 7308c2e..ed28f49 100644
--- a/src/nact/nact-marshal.def
+++ b/src/nact/nact-marshal.def
@@ -1,3 +1,6 @@
+# NactTreeView:: signals
+VOID:POINTER,POINTER
+#
 # NactIActionsList::nact-iactions-list-count-updated
 VOID:INT,INT,INT
 #
diff --git a/src/nact/nact-menubar-edit.c b/src/nact/nact-menubar-edit.c
index f1e2d62..5729782 100644
--- a/src/nact/nact-menubar-edit.c
+++ b/src/nact/nact-menubar-edit.c
@@ -224,7 +224,7 @@ nact_menubar_edit_on_cut( GtkAction *gtk_action, NactMainWindow *window )
 		nact_iactions_list_bis_delete( NACT_IACTIONS_LIST( window ), to_delete, TRUE );
 	}
 
-	na_object_unref_selected_items( items );
+	na_object_free_items( items );
 }
 
 /**
@@ -256,7 +256,7 @@ nact_menubar_edit_on_copy( GtkAction *gtk_action, NactMainWindow *window )
 	clipboard = nact_main_window_get_clipboard( window );
 	nact_clipboard_primary_set( clipboard, items, CLIPBOARD_MODE_COPY );
 	update_clipboard_counters( window );
-	na_object_unref_selected_items( items );
+	na_object_free_items( items );
 
 	g_signal_emit_by_name( bar, MENUBAR_SIGNAL_UPDATE_SENSITIVITIES );
 }
@@ -288,7 +288,7 @@ nact_menubar_edit_on_paste( GtkAction *gtk_action, NactMainWindow *window )
 	items = prepare_for_paste( window );
 	if( items ){
 		nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), items, NULL );
-		na_object_unref_items( items );
+		na_object_free_items( items );
 	}
 }
 
@@ -319,7 +319,7 @@ nact_menubar_edit_on_paste_into( GtkAction *gtk_action, NactMainWindow *window )
 	items = prepare_for_paste( window );
 	if( items ){
 		nact_iactions_list_bis_insert_into( NACT_IACTIONS_LIST( window ), items );
-		na_object_unref_items( items );
+		na_object_free_items( items );
 	}
 }
 
@@ -413,10 +413,10 @@ nact_menubar_edit_on_duplicate( GtkAction *gtk_action, NactMainWindow *window )
 		na_object_check_status( obj );
 		dup = g_list_prepend( NULL, obj );
 		nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), dup, it->data );
-		na_object_unref_items( dup );
+		na_object_free_items( dup );
 	}
 
-	na_object_unref_selected_items( items );
+	na_object_free_items( items );
 }
 
 /**
@@ -472,7 +472,7 @@ nact_menubar_edit_on_delete( GtkAction *gtk_action, NactMainWindow *window )
 		nact_iactions_list_bis_delete( NACT_IACTIONS_LIST( window ), to_delete, TRUE );
 	}
 
-	na_object_unref_selected_items( items );
+	na_object_free_items( items );
 }
 
 static GList *
diff --git a/src/nact/nact-menubar-file.c b/src/nact/nact-menubar-file.c
index a0a7242..695b434 100644
--- a/src/nact/nact-menubar-file.c
+++ b/src/nact/nact-menubar-file.c
@@ -124,7 +124,7 @@ nact_menubar_file_on_new_menu( GtkAction *gtk_action, NactMainWindow *window )
 	na_object_check_status( menu );
 	items = g_list_prepend( NULL, menu );
 	nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), items, NULL );
-	na_object_unref_items( items );
+	na_object_free_items( items );
 }
 
 /**
@@ -147,7 +147,7 @@ nact_menubar_file_on_new_action( GtkAction *gtk_action, NactMainWindow *window )
 	na_object_check_status( action );
 	items = g_list_prepend( NULL, action );
 	nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), items, NULL );
-	na_object_unref_items( items );
+	na_object_free_items( items );
 }
 
 /**
@@ -186,7 +186,7 @@ nact_menubar_file_on_new_profile( GtkAction *gtk_action, NactMainWindow *window
 
 	items = g_list_prepend( NULL, profile );
 	nact_iactions_list_bis_insert_items( NACT_IACTIONS_LIST( window ), items, NULL );
-	na_object_unref_items( items );
+	na_object_free_items( items );
 }
 
 /**
diff --git a/src/nact/nact-menubar-maintainer.c b/src/nact/nact-menubar-maintainer.c
index abe68f5..75d13e8 100644
--- a/src/nact/nact-menubar-maintainer.c
+++ b/src/nact/nact-menubar-maintainer.c
@@ -68,7 +68,7 @@ nact_menubar_maintainer_on_dump_selection( GtkAction *action, NactMainWindow *wi
 		na_object_dump( it->data );
 	}
 
-	na_object_unref_selected_items( items );
+	na_object_free_items( items );
 }
 
 /**
diff --git a/src/nact/nact-menubar.c b/src/nact/nact-menubar.c
index 8b2f66b..865c5a4 100644
--- a/src/nact/nact-menubar.c
+++ b/src/nact/nact-menubar.c
@@ -34,25 +34,15 @@
 
 #include <glib/gi18n.h>
 
-#include <api/na-object-api.h>
-
-#include "nact-application.h"
-#include "nact-menubar-priv.h"
-
-/* *** */
-#include <api/na-core-utils.h>
-
-#include <core/na-factory-object.h>
-#include <core/na-iprefs.h>
 #include <core/na-io-provider.h>
 
-#include "nact-iactions-list.h"
-#include "nact-clipboard.h"
+#include "nact-application.h"
 #include "nact-main-statusbar.h"
 #include "nact-main-toolbar.h"
 #include "nact-main-tab.h"
+#include "nact-menubar-priv.h"
 #include "nact-sort-buttons.h"
-/* *** */
+#include "nact-iactions-list.h"
 
 /* private class data
  */
@@ -704,17 +694,10 @@ on_iactions_list_selection_changed( NactMainWindow *window, GList *selected )
 	g_debug( "%s: selected=%p (count=%d)", thisfn, ( void * ) selected, g_list_length( selected ));
 
 	bar->private->count_selected = g_list_length( selected );
-#if 0
 	if( bar->private->selected_items ){
 		bar->private->selected_items = na_object_free_items( bar->private->selected_items );
 	}
-	bar->private->selected_items = na_object_ref_items( selected );
-#else
-	if( bar->private->selected_items ){
-		na_object_unref_selected_items( bar->private->selected_items );
-	}
-	bar->private->selected_items = nact_iactions_list_bis_get_selected_items( NACT_IACTIONS_LIST( window ));
-#endif
+	bar->private->selected_items = na_object_copyref_items( selected );
 
 	if( selected ){
 		/* check if the parent of the first selected item is writable
diff --git a/src/nact/nact-tree-model-dnd.c b/src/nact/nact-tree-model-dnd.c
index 540d7cc..1857cf6 100644
--- a/src/nact/nact-tree-model-dnd.c
+++ b/src/nact/nact-tree-model-dnd.c
@@ -960,7 +960,7 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData  *selec
 	nact_iactions_list_bis_insert_at_path( NACT_IACTIONS_LIST( main_window ), imported, dest );
 	nact_tree_model_dump( model );
 
-	na_object_unref_items( imported );
+	na_object_free_items( imported );
 	na_core_utils_slist_free( parms.uris );
 
 	for( it = parms.results ; it ; it = it->next ){
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index 8a2b949..b389773 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -102,8 +102,9 @@ static NactTreeModel *tree_model_new( BaseWindow *window, GtkTreeView *treeview
 static void           append_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *parent, GtkTreeIter *iter, const NAObject *object );
 static void           display_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *iter, const NAObject *object );
 static gboolean       dump_store( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmDumpStruct *ntm );
-static void           fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview, NAObject *object, gboolean only_actions, GtkTreeIter *parent );
+static void           fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview, NAObject *object, GtkTreeIter *parent );
 static gboolean       filter_visible( GtkTreeModel *store, GtkTreeIter *iter, NactTreeModel *model );
+static gboolean       get_items_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items );
 static void           iter_on_store( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *parent, FnIterOnStore fn, gpointer user_data );
 static gboolean       iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter, FnIterOnStore fn, gpointer user_data );
 static void           remove_if_exists( NactTreeModel *model, GtkTreeModel *store, const NAObject *object );
@@ -296,7 +297,6 @@ tree_model_new( BaseWindow *window, GtkTreeView *treeview )
 
 	g_debug( "%s: window=%p, treeview=%p", thisfn, ( void * ) window, ( void * ) treeview );
 	g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
-	g_return_val_if_fail( NACT_IS_IACTIONS_LIST( window ), NULL );
 	g_return_val_if_fail( GTK_IS_TREE_VIEW( treeview ), NULL );
 
 	ts_model = gtk_tree_store_new(
@@ -346,7 +346,6 @@ nact_tree_model_initial_load( BaseWindow *window, GtkTreeView *treeview )
 
 	g_debug( "%s: window=%p, treeview=%p", thisfn, ( void * ) window, ( void * ) treeview );
 	g_return_if_fail( BASE_IS_WINDOW( window ));
-	g_return_if_fail( NACT_IS_IACTIONS_LIST( window ));
 	g_return_if_fail( GTK_IS_TREE_VIEW( treeview ));
 
 	model = tree_model_new( window, treeview );
@@ -615,13 +614,39 @@ nact_tree_model_fill( NactTreeModel *model, GList *items, gboolean are_profiles_
 		for( it = items ; it ; it = it->next ){
 			duplicate = ( NAObject * ) na_object_duplicate( it->data );
 			na_object_check_status( duplicate );
-			fill_tree_store( ts_model, model->private->treeview, duplicate, are_profiles_displayed, NULL );
+			fill_tree_store( ts_model, model->private->treeview, duplicate, NULL );
 			na_object_unref( duplicate );
 		}
 	}
 }
 
 /**
+ * nact_tree_model_get_items:
+ * @model: this #NactTreeModel object.
+ *
+ * Returns: the content of the current store as a newly allocated list
+ * which should be na_object_free_items() by the caller.
+ */
+GList *
+nact_tree_model_get_items( NactTreeModel *model )
+{
+	GList *items;
+	GtkTreeStore *store;
+
+	g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), NULL );
+
+	items = NULL;
+
+	if( !model->private->dispose_has_run ){
+
+		store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
+		iter_on_store( model, GTK_TREE_MODEL( store ), NULL, ( FnIterOnStore ) get_items_iter, &items );
+	}
+
+	return( items );
+}
+
+/**
  * nact_tree_model_insert:
  * @model: this #NactTreeModel instance.
  * @object: a #NAObject-derived object to be inserted.
@@ -925,8 +950,7 @@ dump_store( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmDumpSt
 }
 
 static void
-fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
-					NAObject *object, gboolean are_profiles_displayed, GtkTreeIter *parent )
+fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview, NAObject *object, GtkTreeIter *parent )
 {
 	static const gchar *thisfn = "nact_tree_model_fill_tree_store";
 	GList *subitems, *it;
@@ -941,7 +965,7 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
 		append_item( model, treeview, parent, &iter, object );
 		subitems = na_object_get_items( object );
 		for( it = subitems ; it ; it = it->next ){
-			fill_tree_store( model, treeview, it->data, are_profiles_displayed, &iter );
+			fill_tree_store( model, treeview, it->data, &iter );
 		}
 
 	} else {
@@ -998,6 +1022,20 @@ filter_visible( GtkTreeModel *store, GtkTreeIter *iter, NactTreeModel *model )
 	return( FALSE );
 }
 
+/*
+ * builds the tree by iterating on the store
+ */
+static gboolean
+get_items_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items )
+{
+	if( gtk_tree_path_get_depth( path ) == 1 ){
+		*items = g_list_prepend( *items, na_object_ref( object ));
+	}
+
+	/* don't stop iteration */
+	return( FALSE );
+}
+
 static void
 iter_on_store( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *parent, FnIterOnStore fn, gpointer user_data )
 {
@@ -1019,18 +1057,17 @@ iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter
 	GtkTreePath *path;
 	gboolean stop;
 
-	gtk_tree_model_get( store, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
 	/* unreffing as soon as we got the pointer so that the ref count is
 	 * unchanged in dump_store
 	 */
+	gtk_tree_model_get( store, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
 	g_object_unref( object );
+
 	g_debug( "nact_tree_model_iter_on_store_item: object=%p (%s, ref_count=%d)",
 			( void * ) object, G_OBJECT_TYPE_NAME( object ), G_OBJECT( object )->ref_count );
 
 	path = gtk_tree_model_get_path( store, iter );
-
 	stop = ( *fn )( model, path, object, user_data );
-
 	gtk_tree_path_free( path );
 
 	if( !stop ){
diff --git a/src/nact/nact-tree-model.h b/src/nact/nact-tree-model.h
index b2b9b76..68f4564 100644
--- a/src/nact/nact-tree-model.h
+++ b/src/nact/nact-tree-model.h
@@ -101,6 +101,7 @@ void         nact_tree_model_display( NactTreeModel *model, NAObject *object );
 void         nact_tree_model_display_order_change( NactTreeModel *model, gint order_mode );
 void         nact_tree_model_dump( NactTreeModel *model );
 void         nact_tree_model_fill( NactTreeModel *model, GList *items, gboolean are_profiles_displayed );
+GList       *nact_tree_model_get_items( NactTreeModel *model );
 GtkTreePath *nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent );
 GtkTreePath *nact_tree_model_insert_into( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent );
 void         nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data );
diff --git a/src/nact/nact-tree-view.c b/src/nact/nact-tree-view.c
new file mode 100644
index 0000000..54f5539
--- /dev/null
+++ b/src/nact/nact-tree-view.c
@@ -0,0 +1,1072 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <api/na-object-api.h>
+
+#include "base-keysyms.h"
+#include "nact-application.h"
+#include "nact-marshal.h"
+#include "nact-tree-view.h"
+#include "nact-tree-model.h"
+
+#include "nact-iactions-list.h"
+
+/* private class data
+ */
+struct _NactTreeViewClassPrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct _NactTreeViewPrivate {
+	gboolean     dispose_has_run;
+
+	/* properties set at instanciation time
+	 */
+	BaseWindow  *window;
+	gchar       *widget_name;
+	gboolean     have_dnd;
+	gboolean     display_profiles;
+
+	/* runtime data
+	 */
+	GtkTreeView *tree_view;
+	gboolean     notify_allowed;
+};
+
+/* instance properties
+ */
+enum {
+	TREE_PROP_0,
+
+	TREE_PROP_WINDOW_ID,
+	TREE_PROP_WIDGET_NAME_ID,
+	TREE_PROP_HAVE_DND_ID,
+	TREE_PROP_DISPLAY_PROFILES_ID,
+
+	TREE_PROP_N_PROPERTIES
+};
+
+/* signals
+ */
+enum {
+	CONTENT_CHANGED,
+	SELECTION_CHANGED,
+	LAST_SIGNAL
+};
+
+/* when toggle collapse/expand rows, we want all rows have the same
+ * behavior, e.g. all rows collapse, or all rows expand
+ * this behavior is fixed by the first rows which will actually be
+ * toggled
+ */
+enum {
+	TOGGLE_UNDEFINED,
+	TOGGLE_COLLAPSE,
+	TOGGLE_EXPAND
+};
+
+/* iter on selection prototype
+ */
+typedef gboolean ( *FnIterOnSelection )( NactTreeView *, GtkTreeModel *, GtkTreeIter *, NAObject *, gpointer );
+
+#define WINDOW_DATA_TREE_VIEW				"window-data-tree-view"
+
+#define VIEW_WINDOW_VOID( window ) \
+	g_return_if_fail( BASE_IS_WINDOW( window )); \
+	NactTreeView *view = ( NactTreeView * ) g_object_get_data( G_OBJECT( window ), WINDOW_DATA_TREE_VIEW ); \
+	g_return_if_fail( NACT_IS_TREE_VIEW( view ));
+
+#define VIEW_WINDOW_VALUE( window, value ) \
+	g_return_val_if_fail( BASE_IS_WINDOW( window ), value ); \
+	NactTreeView *view = ( NactTreeView * ) g_object_get_data( G_OBJECT( window ), WINDOW_DATA_TREE_VIEW ); \
+	g_return_val_if_fail( NACT_IS_TREE_VIEW( view ), value );
+
+static gint          st_signals[ LAST_SIGNAL ] = { 0 };
+static GObjectClass *st_parent_class           = NULL;
+
+static GType    register_type( void );
+static void     class_init( NactTreeViewClass *klass );
+static void     instance_init( GTypeInstance *instance, gpointer klass );
+static void     instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void     instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void     instance_constructed( GObject *object );
+static void     instance_dispose( GObject *application );
+static void     instance_finalize( GObject *application );
+
+static void     on_base_initialize_gtk( BaseWindow *window, GtkWindow *toplevel, gpointer user_data );
+static void     on_base_initialize_view( BaseWindow *window, gpointer user_data );
+static void     on_base_all_widgets_showed( BaseWindow *window, gpointer user_data );
+static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, BaseWindow *window );
+static void     on_treeview_selection_changed( GtkTreeSelection *selection, BaseWindow *window );
+static void     on_content_changed_cleanup_handler( BaseWindow *window, NactTreeView *view, NAObject *edited );
+static void     on_selection_changed_cleanup_handler( BaseWindow *window, NactTreeView *view, GList *selected_items );
+static void     clear_selection( NactTreeView *view );
+static void     extend_selection_to_children( NactTreeView *view, GtkTreeModel *model, GtkTreeIter *parent );
+static GList   *get_selected_items( NactTreeView *view );
+static void     iter_on_selection( NactTreeView *view, FnIterOnSelection fn_iter, gpointer user_data );
+static void     navigate_to_child( NactTreeView *view );
+static void     navigate_to_parent( NactTreeView *view );
+static void     select_row_at_path( NactTreeView *view, GtkTreePath *path );
+static void     select_row_at_path_by_string( NactTreeView *view, const gchar *path );
+static void     toggle_collapse( NactTreeView *view );
+static gboolean toggle_collapse_iter( NactTreeView *view, GtkTreeModel *model, GtkTreeIter *iter, NAObject *object, gpointer user_data );
+static void     toggle_collapse_row( GtkTreeView *treeview, GtkTreePath *path, guint *toggle );
+static void     on_finalizing_window( NactTreeView *view, GObject *window );
+
+GType
+nact_tree_view_get_type( void )
+{
+	static GType type = 0;
+
+	if( !type ){
+		type = register_type();
+	}
+
+	return( type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "nact_tree_view_register_type";
+	GType type;
+
+	static GTypeInfo info = {
+		sizeof( NactTreeViewClass ),
+		( GBaseInitFunc ) NULL,
+		( GBaseFinalizeFunc ) NULL,
+		( GClassInitFunc ) class_init,
+		NULL,
+		NULL,
+		sizeof( NactTreeView ),
+		0,
+		( GInstanceInitFunc ) instance_init
+	};
+
+	g_debug( "%s", thisfn );
+
+	type = g_type_register_static( G_TYPE_OBJECT, "NactTreeView", &info, 0 );
+
+	return( type );
+}
+
+static void
+class_init( NactTreeViewClass *klass )
+{
+	static const gchar *thisfn = "nact_tree_view_class_init";
+	GObjectClass *object_class;
+
+	g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+	st_parent_class = g_type_class_peek_parent( klass );
+
+	object_class = G_OBJECT_CLASS( klass );
+	object_class->get_property = instance_get_property;
+	object_class->set_property = instance_set_property;
+	object_class->constructed = instance_constructed;
+	object_class->dispose = instance_dispose;
+	object_class->finalize = instance_finalize;
+
+	g_object_class_install_property( object_class, TREE_PROP_WINDOW_ID,
+			g_param_spec_pointer(
+					TREE_PROP_WINDOW,
+					"BaseWindow",
+					"The BaseWindow parent",
+					G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
+
+	g_object_class_install_property( object_class, TREE_PROP_WIDGET_NAME_ID,
+			g_param_spec_string(
+					TREE_PROP_WIDGET_NAME,
+					"Widget name",
+					"The name of GtkTreeView widget",
+					"",
+					G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
+
+	g_object_class_install_property( object_class, TREE_PROP_HAVE_DND_ID,
+			g_param_spec_boolean(
+					TREE_PROP_HAVE_DND,
+					"Have DnD",
+					"Whether Drag and Drop operations are implemented",
+					FALSE,
+					G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
+
+	g_object_class_install_property( object_class, TREE_PROP_DISPLAY_PROFILES_ID,
+			g_param_spec_boolean(
+					TREE_PROP_DISPLAY_PROFILES,
+					"Display profiles",
+					"Whether actions profiles are displayed",
+					FALSE,
+					G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE ));
+
+	/**
+	 * NactTreeView::tree-signal-content-changed:
+	 *
+	 * This signal is emitted on the BaseWindow parent when the content
+	 * of the tree changes. It may change in two occurrences:
+	 * - the whole model is refilled with a new items list;
+	 * - a row is edited.
+	 *
+	 * Signal args:
+	 * - a pointer on the view
+	 * - a poointer on the edited NAObject element, or NULL if the whole
+	 *   list has changed.
+	 *
+	 * Handler prototype:
+	 * void ( *handler )( BaseWindow *window, NactTreeView *view, NAObject *edited, gpointer user_data );
+	 */
+	st_signals[ CONTENT_CHANGED ] = g_signal_new_class_handler(
+			TREE_SIGNAL_CONTENT_CHANGED,
+			G_TYPE_OBJECT,
+			G_SIGNAL_RUN_CLEANUP,
+			G_CALLBACK( on_content_changed_cleanup_handler ),
+			NULL,
+			NULL,
+			nact_cclosure_marshal_VOID__POINTER_POINTER,
+			G_TYPE_NONE,
+			2,
+			G_TYPE_POINTER, G_TYPE_POINTER );
+
+	/**
+	 * NactTreeView::tree-signal-selection-changed:
+	 *
+	 * This signal is emitted on the BaseWindow parent each time the selection
+	 * has changed in the treeview.
+	 *
+	 * Signal args:
+	 * - a pointer on the view
+	 * - a #GList of currently selected #NAObjectItems.
+	 *
+	 * Handler prototype:
+	 * void ( *handler )( BaseWindow *window, NactTreeView *view, GList *selected, gpointer user_data );
+	 */
+	st_signals[ SELECTION_CHANGED ] = g_signal_new_class_handler(
+			TREE_SIGNAL_SELECTION_CHANGED,
+			G_TYPE_OBJECT,
+			G_SIGNAL_RUN_CLEANUP,
+			G_CALLBACK( on_selection_changed_cleanup_handler ),
+			NULL,
+			NULL,
+			nact_cclosure_marshal_VOID__POINTER_POINTER,
+			G_TYPE_NONE,
+			2,
+			G_TYPE_POINTER, G_TYPE_POINTER );
+
+	klass->private = g_new0( NactTreeViewClassPrivate, 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+	static const gchar *thisfn = "nact_tree_view_instance_init";
+	NactTreeView *self;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( instance ));
+
+	g_debug( "%s: instance=%p (%s), klass=%p",
+			thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
+
+	self = NACT_TREE_VIEW( instance );
+
+	self->private = g_new0( NactTreeViewPrivate, 1 );
+
+	self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+	NactTreeView *self;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( object ));
+	self = NACT_TREE_VIEW( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case TREE_PROP_WINDOW_ID:
+				g_value_set_pointer( value, self->private->window );
+				break;
+
+			case TREE_PROP_WIDGET_NAME_ID:
+				g_value_set_string( value, self->private->widget_name );
+				break;
+
+			case TREE_PROP_HAVE_DND_ID:
+				g_value_set_boolean( value, self->private->have_dnd );
+				break;
+
+			case TREE_PROP_DISPLAY_PROFILES_ID:
+				g_value_set_boolean( value, self->private->display_profiles );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+	NactTreeView *self;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( object ));
+	self = NACT_TREE_VIEW( object );
+
+	if( !self->private->dispose_has_run ){
+
+		switch( property_id ){
+			case TREE_PROP_WINDOW_ID:
+				self->private->window = g_value_get_pointer( value );
+				break;
+
+			case TREE_PROP_WIDGET_NAME_ID:
+				g_free( self->private->widget_name );
+				self->private->widget_name = g_value_dup_string( value );
+				break;
+
+			case TREE_PROP_HAVE_DND_ID:
+				self->private->have_dnd = g_value_get_boolean( value );
+				break;
+
+			case TREE_PROP_DISPLAY_PROFILES_ID:
+				self->private->display_profiles = g_value_get_boolean( value );
+				break;
+
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+				break;
+		}
+	}
+}
+
+static void
+instance_constructed( GObject *object )
+{
+	static const gchar *thisfn = "nact_tree_view_instance_constructed";
+	NactTreeView *self;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( object ));
+	self = NACT_TREE_VIEW( object );
+
+	if( !self->private->dispose_has_run ){
+		g_debug( "%s: object=%p", thisfn, ( void * ) object );
+
+		base_window_signal_connect( self->private->window,
+				G_OBJECT( self->private->window ), BASE_SIGNAL_INITIALIZE_GTK, G_CALLBACK( on_base_initialize_gtk ));
+
+		base_window_signal_connect( self->private->window,
+				G_OBJECT( self->private->window ), BASE_SIGNAL_INITIALIZE_WINDOW, G_CALLBACK( on_base_initialize_view ));
+
+		base_window_signal_connect( self->private->window,
+				G_OBJECT( self->private->window ), BASE_SIGNAL_ALL_WIDGETS_SHOWED, G_CALLBACK( on_base_all_widgets_showed ));
+
+		g_object_set_data( G_OBJECT( self->private->window ), WINDOW_DATA_TREE_VIEW, self );
+
+		g_object_weak_ref( G_OBJECT( self->private->window ), ( GWeakNotify ) on_finalizing_window, self );
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->constructed ){
+			G_OBJECT_CLASS( st_parent_class )->constructed( object );
+		}
+	}
+}
+
+static void
+instance_dispose( GObject *object )
+{
+	static const gchar *thisfn = "nact_tree_view_instance_dispose";
+	NactTreeView *self;
+	NactTreeModel *model;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( object ));
+
+	self = NACT_TREE_VIEW( object );
+
+	if( !self->private->dispose_has_run ){
+		g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+
+		self->private->dispose_has_run = TRUE;
+
+		model = NACT_TREE_MODEL( gtk_tree_view_get_model( self->private->tree_view ));
+		nact_tree_model_dispose( model );
+
+		/* chain up to the parent class */
+		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+			G_OBJECT_CLASS( st_parent_class )->dispose( object );
+		}
+	}
+}
+
+static void
+instance_finalize( GObject *instance )
+{
+	static const gchar *thisfn = "nact_tree_view_instance_finalize";
+	NactTreeView *self;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( instance ));
+
+	g_debug( "%s: instance=%p (%s)", thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ));
+
+	self = NACT_TREE_VIEW( instance );
+
+	g_free( self->private->widget_name );
+
+	g_free( self->private );
+
+	/* chain call to parent class */
+	if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+		G_OBJECT_CLASS( st_parent_class )->finalize( instance );
+	}
+}
+
+/**
+ * nact_tree_view_new:
+ * @window: the BaseWindow which embeds the tree view.
+ * @treeview_name: the GtkTreeView widget name.
+ *
+ * Returns: a newly allocated NactTreeView object, which will be owned
+ * by the caller. It is useless to unref it as it will automatically
+ * auto-destroys itself at @window finalization.
+ */
+NactTreeView *
+nact_tree_view_new( BaseWindow *window, const gchar *treeview_name )
+{
+	NactTreeView *view;
+
+	view = g_object_new( NACT_TREE_VIEW_TYPE,
+			TREE_PROP_WINDOW,      window,
+			TREE_PROP_WIDGET_NAME, treeview_name,
+			NULL );
+
+	return( view );
+}
+
+static void
+on_base_initialize_gtk( BaseWindow *window, GtkWindow *toplevel, gpointer user_data )
+{
+	static const gchar *thisfn = "nact_tree_view_on_base_initialize_gtk";
+	GtkTreeView *treeview;
+	GtkWidget *label;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *renderer;
+	GtkTreeSelection *selection;
+
+	VIEW_WINDOW_VOID( window );
+
+	g_debug( "%s: window=%p (%s), toplevel=%p (%s), user_data=%p",
+			thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ),
+			( void * ) toplevel, G_OBJECT_TYPE_NAME( toplevel ), ( void * ) user_data );
+
+	if( !view->private->dispose_has_run ){
+
+		treeview = GTK_TREE_VIEW( base_window_get_widget( window, view->private->widget_name ));
+
+		/* associates the ItemsView to the label */
+		label = base_window_get_widget( window, "ActionsListLabel" );
+		gtk_label_set_mnemonic_widget( GTK_LABEL( label ), GTK_WIDGET( treeview ));
+
+		nact_tree_model_initial_load( window, treeview );
+		gtk_tree_view_set_enable_tree_lines( treeview, TRUE );
+
+		/* create visible columns on the tree view
+		 */
+		column = gtk_tree_view_column_new_with_attributes(
+				"icon",
+				gtk_cell_renderer_pixbuf_new(),
+				"pixbuf", TREE_COLUMN_ICON,
+				NULL );
+		gtk_tree_view_append_column( treeview, column );
+
+		renderer = gtk_cell_renderer_text_new();
+		column = gtk_tree_view_column_new_with_attributes(
+				"label",
+				renderer,
+				"text", TREE_COLUMN_LABEL,
+				NULL );
+		gtk_tree_view_column_set_sort_column_id( column, TREE_COLUMN_LABEL );
+		gtk_tree_view_append_column( treeview, column );
+
+		/* allow multiple selection
+		 */
+		selection = gtk_tree_view_get_selection( treeview );
+		gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE );
+	}
+}
+
+static void
+on_base_initialize_view( BaseWindow *window, gpointer user_data )
+{
+	static const gchar *thisfn = "nact_tree_view_on_base_initialize_view";
+	GtkTreeView *treeview;
+	NactTreeModel *model;
+	GtkTreeSelection *selection;
+
+	VIEW_WINDOW_VOID( window );
+
+	g_debug( "%s: window=%p (%s), user_data=%p",
+			thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ), ( void * ) user_data );
+
+	if( !view->private->dispose_has_run ){
+
+		treeview = GTK_TREE_VIEW( base_window_get_widget( window, view->private->widget_name ));
+		view->private->tree_view = treeview;
+
+		model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+		nact_tree_model_runtime_init( model, view->private->have_dnd );
+
+		/* set up selection control */
+		selection = gtk_tree_view_get_selection( treeview );
+		base_window_signal_connect( window,
+				G_OBJECT( selection ), "changed", G_CALLBACK( on_treeview_selection_changed ));
+
+		/* expand/collapse with the keyboard */
+		base_window_signal_connect( window,
+				G_OBJECT( treeview ), "key-press-event", G_CALLBACK( on_key_pressed_event ));
+	}
+}
+
+static void
+on_base_all_widgets_showed( BaseWindow *window, gpointer user_data )
+{
+	static const gchar *thisfn = "nact_tree_view_on_base_all_widgets_showed";
+
+	VIEW_WINDOW_VOID( window );
+
+	g_debug( "%s: window=%p (%s), user_data=%p",
+			thisfn, ( void * ) window, G_OBJECT_TYPE_NAME( window ), ( void * ) user_data );
+
+	if( !view->private->dispose_has_run ){
+
+		/* force the treeview to have the focus at start
+		 * and select the first row if it exists
+		 */
+		gtk_widget_grab_focus( GTK_WIDGET( view->private->tree_view ));
+		view->private->notify_allowed = TRUE;
+		select_row_at_path_by_string( view, "0" );
+	}
+}
+
+static gboolean
+on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, BaseWindow *window )
+{
+	gboolean stop = FALSE;
+
+	VIEW_WINDOW_VALUE( window, FALSE );
+
+	if( !view->private->dispose_has_run ){
+
+		if( event->keyval == NACT_KEY_Return || event->keyval == NACT_KEY_KP_Enter ){
+			toggle_collapse( view );
+			stop = TRUE;
+		}
+		if( event->keyval == NACT_KEY_Right ){
+			navigate_to_child( view );
+			stop = TRUE;
+		}
+		if( event->keyval == NACT_KEY_Left ){
+			navigate_to_parent( view );
+			stop = TRUE;
+		}
+	}
+
+	return( stop );
+}
+
+/*
+ * handles the "changed" signal emitted on the GtkTreeSelection
+ */
+static void
+on_treeview_selection_changed( GtkTreeSelection *selection, BaseWindow *window )
+{
+	static const gchar *thisfn = "nact_tree_view_on_treeview_selection_changed";
+	GList *selected_items;
+
+	VIEW_WINDOW_VOID( window );
+
+	g_debug( "%s: selection=%p, window=%p", thisfn, ( void * ) selection, ( void * ) window );
+
+	if( !view->private->dispose_has_run ){
+
+		if( view->private->notify_allowed ){
+			selected_items = get_selected_items( view );
+			g_signal_emit_by_name( window, TREE_SIGNAL_SELECTION_CHANGED, view, selected_items );
+		}
+	}
+}
+
+/*
+ * cleanup handler for our TREE_SIGNAL_CONTENT_CHANGED signal
+ */
+static void
+on_content_changed_cleanup_handler( BaseWindow *window, NactTreeView *view, NAObject *edited )
+{
+	static const gchar *thisfn = "nact_tree_view_on_content_changed_cleanup_handler";
+
+	g_debug( "%s: window=%p, view=%p, edited=%p",
+			thisfn, ( void * ) window, ( void * ) view, ( void * ) edited );
+
+	if( edited ){
+		na_object_unref( edited );
+	}
+}
+
+/*
+ * cleanup handler for our TREE_SIGNAL_SELECTION_CHANGED signal
+ */
+static void
+on_selection_changed_cleanup_handler( BaseWindow *window, NactTreeView *view, GList *selected_items )
+{
+	static const gchar *thisfn = "nact_tree_view_on_selection_changed_cleanup_handler";
+
+	g_debug( "%s: window=%p, view=%p, selected_items=%p (count=%u)",
+			thisfn, ( void * ) window, ( void * ) view,
+			( void * ) selected_items, g_list_length( selected_items ));
+
+	na_object_free_items( selected_items );
+}
+
+/**
+ * nact_tree_view_fill:
+ * @view: this #NactTreeView instance.
+ *
+ * Fill the tree view with the provided list of items.
+ *
+ * Notification of selection changes is temporary suspended during the
+ * fillup of the list, so that client is not cluttered with tons of
+ * selection-changed messages.
+ */
+void
+nact_tree_view_fill( NactTreeView *view, GList *items )
+{
+	static const gchar *thisfn = "nact_tree_view_fill";
+	NactTreeModel *model;
+	gboolean prev;
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( view ));
+
+	if( !view->private->dispose_has_run ){
+		g_debug( "%s: view=%p, items=%p (count=%u)",
+				thisfn, ( void * ) view, ( void * ) items, g_list_length( items ));
+
+		clear_selection( view );
+		prev = view->private->notify_allowed;
+		view->private->notify_allowed = FALSE;
+		model = NACT_TREE_MODEL( gtk_tree_view_get_model( view->private->tree_view ));
+		nact_tree_model_fill( model, items, view->private->display_profiles );
+		view->private->notify_allowed = prev;
+
+		if( view->private->notify_allowed ){
+			g_signal_emit_by_name( view->private->window, TREE_SIGNAL_CONTENT_CHANGED, view, NULL );
+		}
+	}
+}
+
+/**
+ * nact_tree_view_get_items:
+ * @view: this #NactTreeView instance.
+ *
+ * Returns: the content of the current tree as a newly allocated list
+ * which should be na_object_free_items() by the caller.
+ */
+GList *
+nact_tree_view_get_items( NactTreeView *view )
+{
+	GList *items;
+	NactTreeModel *model;
+
+	g_return_val_if_fail( NACT_IS_TREE_VIEW( view ), NULL );
+
+	items = NULL;
+
+	if( !view->private->dispose_has_run ){
+
+		model = NACT_TREE_MODEL( gtk_tree_view_get_model( view->private->tree_view ));
+		items = nact_tree_model_get_items( model );
+	}
+
+	return( items );
+}
+
+static void
+clear_selection( NactTreeView *view )
+{
+	GtkTreeSelection *selection;
+
+	selection = gtk_tree_view_get_selection( view->private->tree_view );
+	gtk_tree_selection_unselect_all( selection );
+}
+
+/*
+ * when expanding a selected row which has childs
+ */
+static void
+extend_selection_to_children( NactTreeView *view, GtkTreeModel *model, GtkTreeIter *parent )
+{
+	GtkTreeSelection *selection;
+	GtkTreeIter iter;
+	gboolean ok;
+
+	selection = gtk_tree_view_get_selection( view->private->tree_view );
+	ok = gtk_tree_model_iter_children( model, &iter, parent );
+
+	while( ok ){
+		GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+		gtk_tree_selection_select_path( selection, path );
+		gtk_tree_path_free( path );
+		ok = gtk_tree_model_iter_next( model, &iter );
+	}
+}
+
+/*
+ * get_selected_items:
+ * @view: this #NactTreeView instance.
+ *
+ * We acquire here a new reference on objects corresponding to actually
+ * selected rows, and their children.
+ *
+ * Returns: the currently selected rows as a #GList of #NAObjectItems
+ * which should be na_object_free_items() by the caller.
+ */
+static GList *
+get_selected_items( NactTreeView *view )
+{
+	static const gchar *thisfn = "nact_tree_view_get_selected_items";
+	GList *items;
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	GList *it, *listrows;
+	NAObjectId *object;
+
+	items = NULL;
+	selection = gtk_tree_view_get_selection( view->private->tree_view );
+	listrows = gtk_tree_selection_get_selected_rows( selection, &model );
+
+	for( it = listrows ; it ; it = it->next ){
+		path = ( GtkTreePath * ) it->data;
+		gtk_tree_model_get_iter( model, &iter, path );
+		gtk_tree_model_get( model, &iter, TREE_COLUMN_NAOBJECT, &object, -1 );
+		g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+		items = g_list_prepend( items, na_object_ref( object ));
+		g_object_unref( object );
+	}
+
+	g_list_foreach( listrows, ( GFunc ) gtk_tree_path_free, NULL );
+	g_list_free( listrows );
+
+	return( g_list_reverse( items ));
+}
+
+static void
+iter_on_selection( NactTreeView *view, FnIterOnSelection fn_iter, gpointer user_data )
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GList *listrows, *ipath;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	NAObject *object;
+	gboolean stop;
+
+	stop = FALSE;
+	selection = gtk_tree_view_get_selection( view->private->tree_view );
+	listrows = gtk_tree_selection_get_selected_rows( selection, &model );
+	listrows = g_list_reverse( listrows );
+
+	for( ipath = listrows ; !stop && ipath ; ipath = ipath->next ){
+		path = ( GtkTreePath * ) ipath->data;
+		gtk_tree_model_get_iter( model, &iter, path );
+		gtk_tree_model_get( model, &iter, TREE_COLUMN_NAOBJECT, &object, -1 );
+
+		stop = fn_iter( view, model, &iter, object, user_data );
+
+		g_object_unref( object );
+	}
+
+	g_list_foreach( listrows, ( GFunc ) gtk_tree_path_free, NULL );
+	g_list_free( listrows );
+}
+
+/*
+ * navigate_to_child:
+ * @view: this #NactTreeView object.
+ *
+ * On right arrow, if collapsed, then expand
+ * if already expanded, then goto first child
+ *
+ * Note:
+ * a row which does not have any child is always considered as collapsed;
+ * trying to expand it has no visible effect.
+ */
+static void
+navigate_to_child( NactTreeView *view )
+{
+	GtkTreeSelection *selection;
+	GList *listrows;
+	GtkTreeModel *model;
+	GtkTreePath *path;
+	GtkTreeIter iter;
+	GtkTreePath *child_path;
+
+	selection = gtk_tree_view_get_selection( view->private->tree_view );
+	listrows = gtk_tree_selection_get_selected_rows( selection, &model );
+
+	if( g_list_length( listrows ) == 1 ){
+		path = ( GtkTreePath * ) listrows->data;
+
+		if( !gtk_tree_view_row_expanded( view->private->tree_view, path )){
+			gtk_tree_view_expand_row( view->private->tree_view, path, FALSE );
+
+		} else {
+			gtk_tree_model_get_iter( model, &iter, path );
+
+			if( gtk_tree_model_iter_has_child( model, &iter )){
+				child_path = gtk_tree_path_copy( path );
+				gtk_tree_path_append_index( child_path, 0 );
+				select_row_at_path( view, child_path );
+				gtk_tree_path_free( child_path );
+			}
+		}
+	}
+
+	g_list_foreach( listrows, ( GFunc ) gtk_tree_path_free, NULL );
+	g_list_free( listrows );
+}
+
+/*
+ * navigate_to_parent:
+ * @view: this #NactTreeView object.
+ *
+ * On left arrow, go to the parent.
+ * if already on a parent, collapse it
+ * if already collapsed, up to the next parent
+ *
+ * e.g. path="2:0", depth=2
+ * this means that depth is always >= 1, with depth=1 being the root.
+ */
+static void
+navigate_to_parent( NactTreeView *view )
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GList *listrows;
+	GtkTreePath *path;
+	GtkTreePath *parent_path;
+
+	selection = gtk_tree_view_get_selection( view->private->tree_view );
+	listrows = gtk_tree_selection_get_selected_rows( selection, &model );
+
+	if( g_list_length( listrows ) == 1 ){
+		path = ( GtkTreePath * ) listrows->data;
+
+		if( gtk_tree_view_row_expanded( view->private->tree_view, path )){
+			gtk_tree_view_collapse_row( view->private->tree_view, path );
+
+		} else if( gtk_tree_path_get_depth( path ) > 1 ){
+			parent_path = gtk_tree_path_copy( path );
+			gtk_tree_path_up( parent_path );
+			select_row_at_path( view, parent_path );
+			gtk_tree_path_free( parent_path );
+		}
+	}
+
+	g_list_foreach( listrows, ( GFunc ) gtk_tree_path_free, NULL );
+	g_list_free( listrows );
+}
+
+/*
+ * Select the row at the required path, or the immediate previous, or
+ * the next following, or eventually the immediate parent.
+ *
+ * If nothing can be selected (and notify is allowed), at least send a
+ * message with an empty selection.
+ */
+static void
+select_row_at_path( NactTreeView *view, GtkTreePath *path )
+{
+	static const gchar *thisfn = "nact_tree_view_select_row_at_path";
+	gchar *path_str;
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	gboolean something = FALSE;
+
+	path_str = gtk_tree_path_to_string( path );
+	g_debug( "%s: view=%p, path=%s", thisfn, ( void * ) view, path_str );
+	g_free( path_str );
+
+	if( path ){
+		gtk_tree_view_expand_to_path( view->private->tree_view, path );
+		model = gtk_tree_view_get_model( view->private->tree_view );
+
+		if( gtk_tree_model_get_iter( model, &iter, path )){
+			gtk_tree_view_set_cursor( view->private->tree_view, path, NULL, FALSE );
+			something = TRUE;
+
+		} else if( gtk_tree_path_prev( path ) && gtk_tree_model_get_iter( model, &iter, path )){
+			gtk_tree_view_set_cursor( view->private->tree_view, path, NULL, FALSE );
+			something = TRUE;
+
+		} else {
+			gtk_tree_path_next( path );
+			if( gtk_tree_model_get_iter( model, &iter, path )){
+				gtk_tree_view_set_cursor( view->private->tree_view, path, NULL, FALSE );
+				something = TRUE;
+
+			} else if( gtk_tree_path_get_depth( path ) > 1 &&
+						gtk_tree_path_up( path ) &&
+						gtk_tree_model_get_iter( model, &iter, path )){
+
+							gtk_tree_view_set_cursor( view->private->tree_view, path, NULL, FALSE );
+							something = TRUE;
+			}
+		}
+	}
+
+	if( !something ){
+		if( view->private->notify_allowed ){
+			g_signal_emit_by_name( view->private->window, TREE_SIGNAL_SELECTION_CHANGED, view, NULL );
+		}
+	}
+}
+
+static void
+select_row_at_path_by_string( NactTreeView *view, const gchar *path_str )
+{
+	GtkTreePath *path;
+
+	path = gtk_tree_path_new_from_string( path_str );
+	select_row_at_path( view, path );
+	gtk_tree_path_free( path );
+}
+
+/*
+ * Toggle or collapse the current subtree.
+ */
+static void
+toggle_collapse( NactTreeView *view )
+{
+	guint toggle = TOGGLE_UNDEFINED;
+
+	iter_on_selection( view, ( FnIterOnSelection ) toggle_collapse_iter, &toggle );
+}
+
+static gboolean
+toggle_collapse_iter( NactTreeView *view, GtkTreeModel *model,
+						GtkTreeIter *iter, NAObject *object, gpointer user_data )
+{
+	guint count;
+	guint *toggle;
+
+	toggle = ( guint * ) user_data;
+
+	if( NA_IS_OBJECT_ITEM( object )){
+		GtkTreePath *path = gtk_tree_model_get_path( model, iter );
+		count = na_object_get_items_count( object );
+
+		if(( count > 1 && NA_IS_OBJECT_ACTION( object )) ||
+			( count > 0 && NA_IS_OBJECT_MENU( object ))){
+
+			toggle_collapse_row( view->private->tree_view, path, toggle );
+		}
+
+		gtk_tree_path_free( path );
+
+		/* do not extend selection to children */
+		if( 0 ){
+			if( *toggle == TOGGLE_EXPAND ){
+				extend_selection_to_children( view, model, iter );
+			}
+		}
+	}
+
+	/* do not stop iteration */
+	return( FALSE );
+}
+
+/*
+ * toggle mode can be undefined, collapse or expand
+ * it is set on the first row
+ */
+static void
+toggle_collapse_row( GtkTreeView *treeview, GtkTreePath *path, guint *toggle )
+{
+	if( *toggle == TOGGLE_UNDEFINED ){
+		*toggle = gtk_tree_view_row_expanded( treeview, path ) ? TOGGLE_COLLAPSE : TOGGLE_EXPAND;
+	}
+
+	if( *toggle == TOGGLE_COLLAPSE ){
+		if( gtk_tree_view_row_expanded( treeview, path )){
+			gtk_tree_view_collapse_row( treeview, path );
+		}
+	} else {
+		if( !gtk_tree_view_row_expanded( treeview, path )){
+			gtk_tree_view_expand_row( treeview, path, TRUE );
+		}
+	}
+}
+
+static void
+on_finalizing_window( NactTreeView *view, GObject *window )
+{
+	static const gchar *thisfn = "nact_tree_view_on_finalizing_window";
+
+	g_return_if_fail( NACT_IS_TREE_VIEW( view ));
+
+	g_debug( "%s: view=%p (%s), window=%p",
+			thisfn, ( void * ) view, G_OBJECT_TYPE_NAME( view ), ( void * ) window );
+
+	g_object_unref( view );
+}
+
+void
+nact_tree_view_setup_ialid( const NactTreeView *view, IActionsListInstanceData *ialid )
+{
+	g_return_if_fail( NACT_IS_TREE_VIEW( view ));
+
+	if( !view->private->dispose_has_run ){
+
+		ialid->management_mode = IACTIONS_LIST_MANAGEMENT_MODE_EXPORT;
+		/*ialid->menus;*/
+		/*ialid->actions;*/
+		/*ialid->profiles;*/
+		ialid->selection_changed_allowed = view->private->notify_allowed;
+		/*ialid->tab_updated_handler;*/
+		/*ialid->modified_items;*/
+	}
+}
diff --git a/src/nact/nact-tree-view.h b/src/nact/nact-tree-view.h
new file mode 100644
index 0000000..8390dea
--- /dev/null
+++ b/src/nact/nact-tree-view.h
@@ -0,0 +1,117 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * This Program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifndef __NACT_TREE_VIEW_H__
+#define __NACT_TREE_VIEW_H__
+
+/*
+ * SECTION: nact-tree-view
+ * @title: NactTreeView
+ * @short_description: The Tree View Base Class Definition
+ * @include: nact-tree-view.h
+ *
+ * This is a convenience class to manage a read-only items tree view.
+ */
+
+#include "base-window.h"
+
+G_BEGIN_DECLS
+
+#define NACT_TREE_VIEW_TYPE                ( nact_tree_view_get_type())
+#define NACT_TREE_VIEW( object )           ( G_TYPE_CHECK_INSTANCE_CAST( object, NACT_TREE_VIEW_TYPE, NactTreeView ))
+#define NACT_TREE_VIEW_CLASS( klass )      ( G_TYPE_CHECK_CLASS_CAST( klass, NACT_TREE_VIEW_TYPE, NactTreeViewClass ))
+#define NACT_IS_TREE_VIEW( object )        ( G_TYPE_CHECK_INSTANCE_TYPE( object, NACT_TREE_VIEW_TYPE ))
+#define NACT_IS_TREE_VIEW_CLASS( klass )   ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NACT_TREE_VIEW_TYPE ))
+#define NACT_TREE_VIEW_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NACT_TREE_VIEW_TYPE, NactTreeViewClass ))
+
+typedef struct _NactTreeViewPrivate        NactTreeViewPrivate;
+
+typedef struct {
+	/*< private >*/
+	GObject              parent;
+	NactTreeViewPrivate *private;
+}
+	NactTreeView;
+
+typedef struct _NactTreeViewClassPrivate   NactTreeViewClassPrivate;
+
+typedef struct {
+	/*< private >*/
+	GObjectClass              parent;
+	NactTreeViewClassPrivate *private;
+}
+	NactTreeViewClass;
+
+/**
+ * Properties defined by the NactTreeView class.
+ * They should be provided at object instantiation time.
+ *
+ * @TREE_PROP_WINDOW:           the BaseWindow parent.
+ * @TREE_PROP_WIDGET_NAME:      the widget name.
+ * @TREE_PROP_HAVE_DND:         whether drag and drop is implemented.
+ * @TREE_PROP_DISPLAY_PROFILES: whether profiles are displayed.
+ */
+#define TREE_PROP_WINDOW					"tree-prop-window"
+#define TREE_PROP_WIDGET_NAME				"tree-prop-widget-name"
+#define TREE_PROP_HAVE_DND					"tree-prop-have-dnd"
+#define TREE_PROP_DISPLAY_PROFILES			"tree-prop-display-profiles"
+
+/**
+ * Column ordering in the tree view
+ */
+enum {
+	TREE_COLUMN_ICON = 0,
+	TREE_COLUMN_LABEL,
+	TREE_COLUMN_NAOBJECT,
+	TREE_N_COLUMN
+};
+
+/**
+ * Signals emitted by the NactTreeView instance.
+ */
+#define TREE_SIGNAL_CONTENT_CHANGED			"tree-signal-content-changed"
+#define TREE_SIGNAL_SELECTION_CHANGED		"tree-signal-selection-changed"
+
+GType         nact_tree_view_get_type( void );
+
+NactTreeView *nact_tree_view_new( BaseWindow *window, const gchar *treeview_name );
+
+void          nact_tree_view_fill     ( NactTreeView *view, GList *items );
+GList        *nact_tree_view_get_items( NactTreeView *view );
+
+/* special transition phase
+ */
+#include "nact-iactions-list-priv.h"
+
+void nact_tree_view_setup_ialid( const NactTreeView *view, IActionsListInstanceData *ialid );
+
+G_END_DECLS
+
+#endif /* __NACT_TREE_VIEW_H__ */
diff --git a/src/plugin-menu/nautilus-actions.c b/src/plugin-menu/nautilus-actions.c
index da37329..4e4b10a 100644
--- a/src/plugin-menu/nautilus-actions.c
+++ b/src/plugin-menu/nautilus-actions.c
@@ -487,7 +487,7 @@ get_menus_items( NautilusActions *plugin, guint target, GList *selection )
 
 	menus_list = build_nautilus_menus( plugin, copy_tree, target, selection, tokens );
 
-	na_object_unref_items( copy_tree );
+	na_object_free_items( copy_tree );
 	g_object_unref( tokens );
 
 	if( target != ITEM_TARGET_TOOLBAR ){



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