[nautilus-actions] Cleanup NAIDuplicable signal propagation code



commit cbcf691ff06fcbc139369f0d92a223861ee0d5eb
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Sep 21 22:04:21 2009 +0200

    Cleanup NAIDuplicable signal propagation code

 src/common/na-iduplicable.c    |   78 +++++++++++++++------------------------
 src/common/na-iduplicable.h    |    8 ++---
 src/common/na-object-item-fn.h |   17 ++++++++-
 src/nact/nact-iactions-list.c  |   28 +++++----------
 src/nact/nact-main-menubar.c   |   66 ++++++++++++++-------------------
 src/nact/nact-tree-model.c     |   17 ++++++---
 6 files changed, 96 insertions(+), 118 deletions(-)
---
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
index 92f897d..6a24264 100644
--- a/src/common/na-iduplicable.c
+++ b/src/common/na-iduplicable.c
@@ -50,9 +50,7 @@ struct NAIDuplicableInterfacePrivate {
  */
 enum {
 	MODIFIED_CHANGED,
-	MODIFIED_CHANGED_PROXY,
 	VALID_CHANGED,
-	VALID_CHANGED_PROXY,
 	LAST_SIGNAL
 };
 
@@ -139,6 +137,11 @@ interface_base_init( NAIDuplicableInterface *klass )
 		 *
 		 * This signal is emitted by NAIDuplicable when the modification
 		 * status of an object has been modified.
+		 *
+		 * The default class handler propagates this same signal to
+		 * registered consumers ; the consumer should have taken care
+		 * of overriding the class handler if he doesn't want create an
+		 * infinite loop.
 		 */
 		st_signals[ MODIFIED_CHANGED ] = g_signal_new_class_handler(
 				NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED,
@@ -153,29 +156,15 @@ interface_base_init( NAIDuplicableInterface *klass )
 				G_TYPE_POINTER );
 
 		/**
-		 * na-iduplicable-modified-changed-proxy:
-		 *
-		 * This signal is propagated to consumers when the modification
-		 * status of an object has been modified, as a default interface
-		 * handler for the previous signal.
-		 */
-		st_signals[ MODIFIED_CHANGED_PROXY ] = g_signal_new(
-				NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED_PROXY,
-				G_TYPE_OBJECT,
-				G_SIGNAL_RUN_LAST,
-				0,						/* no default handler */
-				NULL,
-				NULL,
-				g_cclosure_marshal_VOID__POINTER,
-				G_TYPE_NONE,
-				1,
-				G_TYPE_POINTER );
-
-		/**
 		 * na-iduplicable-valid-changed:
 		 *
 		 * This signal is emitted byIDuplicable when the validity
 		 * status of an object has been modified.
+		 *
+		 * The default class handler propagates this same signal to
+		 * registered consumers ; the consumer should have taken care
+		 * of overriding the class handler if he doesn't want create an
+		 * infinite loop.
 		 */
 		st_signals[ VALID_CHANGED ] = g_signal_new_class_handler(
 				NA_IDUPLICABLE_SIGNAL_VALID_CHANGED,
@@ -189,25 +178,6 @@ interface_base_init( NAIDuplicableInterface *klass )
 				1,
 				G_TYPE_POINTER );
 
-		/**
-		 * na-iduplicable-valid-changed-proxy:
-		 *
-		 * This signal is propagated to consumers when the validity
-		 * status of an object has been modified, as a default interface
-		 * handler for the previous signal.
-		 */
-		st_signals[ VALID_CHANGED_PROXY ] = g_signal_new(
-				NA_IDUPLICABLE_SIGNAL_VALID_CHANGED_PROXY,
-				G_TYPE_OBJECT,
-				G_SIGNAL_RUN_LAST,
-				0,						/* no default handler */
-				NULL,
-				NULL,
-				g_cclosure_marshal_VOID__POINTER,
-				G_TYPE_NONE,
-				1,
-				G_TYPE_POINTER );
-
 		st_interface = klass;
 
 		st_initialized = TRUE;
@@ -329,9 +299,15 @@ na_iduplicable_duplicate( const NAIDuplicable *object )
  * %PROP_IDUPLICABLE_ISVALID properties.
  *
  * This function is supposed to be called each time the object may have
- * been modified in order to set these properties. Helper functions
- * na_iduplicable_is_modified() and na_iduplicable_is_valid() will
- * then only return the current value of the properties.
+ * been modified in order to set the corresponding properties. Helper
+ * functions na_iduplicable_is_modified() and na_iduplicable_is_valid()
+ * will then only return the current value of the properties.
+ *
+ * na_iduplicable_check_edition_status() is not, as itself, recursive.
+ * That is, the modification and validity status are only set on the
+ * specified object.
+ * Nonetheless, a derived class may perfectly implement a recursive
+ * check on childs, if any. See, e.g. #NAObjectItem implementation.
  */
 void
 na_iduplicable_check_edition_status( const NAIDuplicable *object )
@@ -344,13 +320,18 @@ na_iduplicable_check_edition_status( const NAIDuplicable *object )
 	gboolean valid;
 
 #if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-	g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+	g_debug( "%s: object=%p (%s)", thisfn,
+			( void * ) object, G_OBJECT_TYPE_NAME( object ));
 #endif
 	g_return_if_fail( st_initialized && !st_finalized );
 	g_return_if_fail( NA_IS_IDUPLICABLE( object ));
 
 	origin = get_origin( object );
 	if( origin ){
+
+		/* order is important, as derived class may rely on having
+		 * origin first, and then checked object itself
+		 */
 		modified = !v_are_equal( origin, object );
 	}
 	set_modified( object, modified );
@@ -359,8 +340,9 @@ na_iduplicable_check_edition_status( const NAIDuplicable *object )
 	set_valid( object, valid );
 
 #if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-	g_debug( "%s: object=%p, modified=%s, valid=%s",
-			thisfn, ( void * ) object, modified ? "True":"False", valid ? "True":"False" );
+	g_debug( "%s: object=%p (%s), modified=%s, valid=%s", thisfn,
+			( void * ) object, G_OBJECT_TYPE_NAME( object ),
+			modified ? "True":"False", valid ? "True":"False" );
 #endif
 }
 
@@ -584,7 +566,7 @@ propagate_modified_changed( NAIDuplicable *instance, gpointer user_data )
 			( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
 			( void * ) user_data, G_OBJECT_TYPE_NAME( user_data ));*/
 
-	propagate_signal_to_consumers( NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED_PROXY, instance, user_data );
+	propagate_signal_to_consumers( NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED, instance, user_data );
 }
 
 static void
@@ -594,7 +576,7 @@ propagate_valid_changed( NAIDuplicable *instance, gpointer user_data )
 			( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
 			( void * ) user_data, G_OBJECT_TYPE_NAME( user_data ));*/
 
-	propagate_signal_to_consumers( NA_IDUPLICABLE_SIGNAL_VALID_CHANGED_PROXY, instance, user_data );
+	propagate_signal_to_consumers( NA_IDUPLICABLE_SIGNAL_VALID_CHANGED, instance, user_data );
 }
 
 static void
diff --git a/src/common/na-iduplicable.h b/src/common/na-iduplicable.h
index 7605e75..a565f52 100644
--- a/src/common/na-iduplicable.h
+++ b/src/common/na-iduplicable.h
@@ -142,12 +142,10 @@ typedef struct {
 }
 	NAIDuplicableInterface;
 
-#define NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED			"na-iduplicable-modified-changed"
-#define NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED_PROXY	"na-iduplicable-modified-changed-proxy"
-#define NA_IDUPLICABLE_SIGNAL_VALID_CHANGED				"na-iduplicable-valid-changed"
-#define NA_IDUPLICABLE_SIGNAL_VALID_CHANGED_PROXY		"na-iduplicable-valid-changed-proxy"
+#define NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED		"na-iduplicable-modified-changed"
+#define NA_IDUPLICABLE_SIGNAL_VALID_CHANGED			"na-iduplicable-valid-changed"
 
-#define NA_IDUPLICABLE_EDITION_STATUS_DEBUG				0
+#define NA_IDUPLICABLE_EDITION_STATUS_DEBUG			0
 
 GType          na_iduplicable_get_type( void );
 
diff --git a/src/common/na-object-item-fn.h b/src/common/na-object-item-fn.h
index b04badf..108a0dc 100644
--- a/src/common/na-object-item-fn.h
+++ b/src/common/na-object-item-fn.h
@@ -36,8 +36,21 @@
  * @short_description: #NAObjectItem class definition.
  * @include: common/na-object-item.h
  *
- * Derived from #NAObjectId class, this class is built to be used as
- * a base class for objects which have a tooltip and an icon.
+ * Derived from #NAObjectId class, this class implements objects which
+ * have :
+ * - a tooltip,
+ * - an icon,
+ * - a list of childs.
+ *
+ * Note that checking edition status of a #NAObjectItem is almost, but
+ * not really a recursive process :
+ * - it may appear as recursive because all childs of the checked
+ *   #NAObjectItem, and childs of childs, etc., are also checked so that
+ *   they are able to setup their individual own edition status ;
+ * - nonetheless, but a particular rule which may be implemented in a
+ *   derived class, the edition status of the checked #NAObjectItem
+ *   itself is computed individually, without regards of the edition
+ *   status of its childs.
  */
 
 #include <gtk/gtk.h>
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 4333770..aa97bfa 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -401,26 +401,16 @@ nact_iactions_list_runtime_init_toplevel( NactIActionsList *instance, GList *ite
 			IACTIONS_LIST_SIGNAL_ITEM_UPDATED,
 			G_CALLBACK( on_iactions_list_item_updated ));
 
+	/* records NactIActionsList as a proxy for edition status modification
+	 */
+	na_iduplicable_register_consumer( G_OBJECT( instance ));
+	g_signal_override_class_handler( NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED, BASE_WINDOW_TYPE, G_CALLBACK( on_edition_status_changed ));
+	g_signal_override_class_handler( NA_IDUPLICABLE_SIGNAL_VALID_CHANGED, BASE_WINDOW_TYPE, G_CALLBACK( on_edition_status_changed ));
+
 	/* fill the model after having connected the signals
 	 * so that callbacks are triggered at last
 	 */
 	nact_iactions_list_fill( instance, items );
-
-	/* records a proxy for edition status modification
-	 */
-	na_iduplicable_register_consumer( G_OBJECT( instance ));
-
-	base_window_signal_connect(
-			BASE_WINDOW( instance ),
-			G_OBJECT( instance ),
-			NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED_PROXY,
-			G_CALLBACK( on_edition_status_changed ));
-
-	base_window_signal_connect(
-			BASE_WINDOW( instance ),
-			G_OBJECT( instance ),
-			NA_IDUPLICABLE_SIGNAL_VALID_CHANGED_PROXY,
-			G_CALLBACK( on_edition_status_changed ));
 }
 
 /**
@@ -705,7 +695,7 @@ nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObj
 		na_object_check_edition_status( it->data );
 	}
 
-	/*gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));*/
+	gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
 	select_row_at_path( instance, treeview, model, last_path );
 
 	gtk_tree_path_free( last_path );
@@ -1271,9 +1261,9 @@ on_edition_status_changed( NactIActionsList *instance, NAIDuplicable *object )
 	GtkTreeView *treeview;
 	NactTreeModel *model;
 
-	/*g_debug( "nact_iactions_list_on_edition_status_changed: instance=%p (%s), object=%p (%s)",
+	g_debug( "nact_iactions_list_on_edition_status_changed: instance=%p (%s), object=%p (%s)",
 			( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
-			( void * ) object, G_OBJECT_TYPE_NAME( object ));*/
+			( void * ) object, G_OBJECT_TYPE_NAME( object ));
 
 	if( is_selection_changed_authorized( instance )){
 		g_return_if_fail( NA_IS_OBJECT( object ));
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index 5d3935d..47e715a 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -60,7 +60,7 @@ static void     on_new_menu_activated( GtkAction *action, NactMainWindow *window
 static void     on_new_action_activated( GtkAction *action, NactMainWindow *window );
 static void     on_new_profile_activated( GtkAction *action, NactMainWindow *window );
 static void     on_save_activated( GtkAction *action, NactMainWindow *window );
-static void     save_object_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *object );
+static void     save_item( NAObject *object, NactMainWindow *window );
 static void     on_quit_activated( GtkAction *action, NactMainWindow *window );
 
 static void     on_cut_activated( GtkAction *action, NactMainWindow *window );
@@ -319,7 +319,6 @@ on_new_profile_activated( GtkAction *gtk_action, NactMainWindow *window )
 	profile = na_object_profile_new();
 
 	name = na_object_action_get_new_profile_name( action );
-	/*na_object_action_attach_profile( action, profile );*/
 	na_object_profile_set_action( profile, action );
 	na_object_set_id( profile, name );
 	na_object_check_edition_status( profile );
@@ -338,26 +337,17 @@ on_new_profile_activated( GtkAction *gtk_action, NactMainWindow *window )
 static void
 on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
 {
-	GList *items, *it;
-	NactApplication *application;
-	NAPivot *pivot;
+	GList *items;
 
 	g_return_if_fail( GTK_IS_ACTION( gtk_action ));
 	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
-	g_return_if_fail( NACT_IS_WINDOW( window ));
 
 	items = nact_iactions_list_get_items( NACT_IACTIONS_LIST( window ));
 	nact_window_write_level_zero( NACT_WINDOW( window ), items );
 
 	/* recursively save the valid modified items
 	 */
-	application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
-	pivot = nact_application_get_pivot( application );
-
-	for( it = items ; it ; it = it->next ){
-		g_return_if_fail( NA_IS_OBJECT_ITEM( it->data ));
-		save_object_item( window, pivot, NA_OBJECT_ITEM( it->data ));
-	}
+	g_list_foreach( items, ( GFunc ) save_item, window );
 
 	/* doesn't unref object owned by the tree store
 	 */
@@ -367,59 +357,59 @@ on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
 	 */
 	nact_main_window_remove_deleted( window );
 
+	/* required as selection has not changed
+	 */
 	nact_main_menubar_refresh_actions_sensitivity( window );
+
+	/* get ride of notification messages of IOProviders
+	 */
 	na_ipivot_consumer_delay_notify( NA_IPIVOT_CONSUMER( window ));
 }
 
 /*
- * recursively saving an object item
- * - add a duplicate of this action to pivot or update the origin
- * - set the duplicate as the origin of this action
- * - reset the status
+ * iterates here on each and every row stored in the tree
+ * - do not deal with profiles as they are directly managed by their
+ *   action parent
+ * - do not deal with not modified, or not valid, items
  */
 static void
-save_object_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *object )
+save_item( NAObject *object, NactMainWindow *window )
 {
-	GList *items, *it;
+	NactApplication *application;
+	NAPivot *pivot;
 	NAObjectItem *origin;
 	NAObjectItem *dup_pivot;
 
-	if( na_object_is_modified( NA_OBJECT( object )) &&
-		na_object_is_valid( NA_OBJECT( object )) &&
-		nact_window_save_item( NACT_WINDOW( window ), object )){
+	g_return_if_fail( NA_IS_OBJECT( object ));
+	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+	if( !NA_IS_OBJECT_PROFILE( object ) &&
+		na_object_is_modified( NA_OBJECT( object )) &&
+		na_object_is_valid( NA_OBJECT( object ))){
 
-			g_debug( "save_object_item: about to get origin" );
-			/* do not use OA_OBJECT_ITEM macro as this may return a (valid)
+		g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+
+		if( nact_window_save_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( object ))){
+
+			/* do not use NA_OBJECT_ITEM macro as this may return a (valid)
 			 * NULL value
 			 */
 			origin = ( NAObjectItem * ) na_object_get_origin( object );
 
 			if( origin ){
-				g_debug( "save_object_item: about to copy to origin" );
 				na_object_copy( origin, object );
 
 			} else {
-				g_debug( "save_object_item: about to duplicate" );
+				application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+				pivot = nact_application_get_pivot( application );
 				dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( object ));
 				na_object_set_origin( dup_pivot, NULL );
 				na_object_set_origin( object, dup_pivot );
 				na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
 			}
 
-			g_debug( "save_object_item: about to check edition status" );
 			na_object_check_edition_status( object );
-	}
-
-	/* Profiles are saved with their actions
-	 * so we only have to take care of menus
-	 */
-	if( NA_IS_OBJECT_MENU( object )){
-		items = na_object_get_items( NA_OBJECT_MENU( object ));
-		for( it = items ; it ; it = it->next ){
-			g_return_if_fail( NA_IS_OBJECT_ITEM( it->data ));
-			save_object_item( window, pivot, NA_OBJECT_ITEM( it->data ));
 		}
-		na_object_free_items( items );
 	}
 }
 
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index e82836b..74432ac 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -499,20 +499,25 @@ nact_tree_model_dispose( NactTreeModel *model )
 void
 nact_tree_model_display( NactTreeModel *model, NAObject *object )
 {
+	static const gchar *thisfn = "nact_tree_model_display";
 	GtkTreeStore *store;
 	GtkTreeIter iter;
 	GtkTreePath *path;
 
+	g_debug( "%s: model=%p (%s), object=%p (%s)", thisfn,
+			( void * ) model, G_OBJECT_TYPE_NAME( model ),
+			( void * ) object, G_OBJECT_TYPE_NAME( object ));
+
 	store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
 
 	if( search_for_object( model, GTK_TREE_MODEL( store ), object, &iter )){
 		display_item( store, model->private->treeview, &iter, object );
+		path = gtk_tree_model_get_path( GTK_TREE_MODEL( store ), &iter );
+		gtk_tree_model_row_changed( GTK_TREE_MODEL( store ), path, &iter );
+		gtk_tree_path_free( path );
 	}
 
 	/*gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));*/
-	path = gtk_tree_model_get_path( GTK_TREE_MODEL( store ), &iter );
-	gtk_tree_model_row_changed( GTK_TREE_MODEL( store ), path, &iter );
-	gtk_tree_path_free( path );
 }
 
 void
@@ -534,7 +539,6 @@ nact_tree_model_dump( NactTreeModel *model )
 	ntm->prefix = g_strdup( "" );
 
 	nact_tree_model_iter( model, ( FnIterOnStore ) dump_store, ntm );
-	/*dump_store( GTK_TREE_MODEL( store ), NULL, thisfn, "" );*/
 
 	g_free( ntm->prefix );
 	g_free( ntm->fname );
@@ -576,7 +580,7 @@ static void
 fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
 					GList *items, gboolean only_actions, GtkTreeIter *parent )
 {
-	/*static const gchar *thisfn = "nact_tree_model_fill_tree_store";*/
+	static const gchar *thisfn = "nact_tree_model_fill_tree_store";
 	GList *subitems, *it;
 	NAObject *object;
 	NAObject *duplicate;
@@ -584,7 +588,8 @@ fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
 
 	for( it = items ; it ; it = it->next ){
 		object = NA_OBJECT( it->data );
-		/*g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );*/
+		g_debug( "%s: object=%p(%s)", thisfn
+				, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
 
 		if( NA_IS_OBJECT_MENU( object )){
 			duplicate = object;



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