[nautilus-actions] Update the tree model on field modifications



commit 9014c3da799319a45e765a7bba3017a657bad201
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Sep 21 20:30:45 2009 +0200

    Update the tree model on field modifications

 ChangeLog                     |    4 +
 src/common/na-iduplicable.c   |  126 ++++++++++++++++++++++++++++++++++++++---
 src/common/na-iduplicable.h   |   10 ++-
 src/nact/nact-iactions-list.c |   41 +++++++++++++-
 src/nact/nact-tree-model.c    |    6 ++-
 5 files changed, 172 insertions(+), 15 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a24531d..d7cdbd7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,7 @@
 	* src/common/na-iduplicable.h:
 	Emits a signal for each modification of one of the status.
 	Do not use NA_xx macros when returning a pointer that may be NULL.
+	Propagate the modification signal to registered consumers.
 
 	* src/common/na-iio-provider.c (build_hierarchy):
 	Defaults to keep the whole list when there is no level-zero pref.
@@ -35,6 +36,8 @@
 	* src/nact/nact-iactions-list.c:
 	When duplicating an object, try to insert the new one besides
 	the original one.
+	Replace calls to gtk_tree_model_refilter() by
+	nact_tree_model_display().
 
 	* src/nact/nact-main-menubar.c (on_new_profile_activated):
 	Setup edition status of new profile.
@@ -46,6 +49,7 @@
 	* src/nact/nact-tree-model.h (nact_tree_model_insert):
 	Returns the path string of the newly inserted row, as it appears
 	more liable that an iter after child model conversion.
+	nact_tree_model_display(): send signal "row-changed".
 
 2009-09-20 Pierre Wieser <pwieser trychlos org>
 
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
index ffbbdc9..92f897d 100644
--- a/src/common/na-iduplicable.c
+++ b/src/common/na-iduplicable.c
@@ -37,7 +37,7 @@
 /* private interface data
  */
 struct NAIDuplicableInterfacePrivate {
-	void *empty;						/* so that gcc -pedantic is happy */
+	GList *consumers;
 };
 
 /* data set against NAIDuplicable-implementated instance
@@ -50,13 +50,16 @@ struct NAIDuplicableInterfacePrivate {
  */
 enum {
 	MODIFIED_CHANGED,
+	MODIFIED_CHANGED_PROXY,
 	VALID_CHANGED,
+	VALID_CHANGED_PROXY,
 	LAST_SIGNAL
 };
 
-static gboolean st_initialized = FALSE;
-static gboolean st_finalized = FALSE ;
-static gint     st_signals[ LAST_SIGNAL ] = { 0 };
+static NAIDuplicableInterface *st_interface = NULL;
+static gboolean                st_initialized = FALSE;
+static gboolean                st_finalized = FALSE ;
+static gint                    st_signals[ LAST_SIGNAL ] = { 0 };
 
 static GType          register_type( void );
 static void           interface_base_init( NAIDuplicableInterface *klass );
@@ -74,6 +77,11 @@ static void           set_modified( const NAIDuplicable *object, gboolean is_mod
 static void           set_origin( const NAIDuplicable *object, const NAIDuplicable *origin );
 static void           set_valid( const NAIDuplicable *object, gboolean is_valid );
 
+static void           propagate_modified_changed( NAIDuplicable *instance, gpointer user_data );
+static void           propagate_valid_changed( NAIDuplicable *instance, gpointer user_data );
+static void           propagate_signal_to_consumers( const gchar *signal, NAIDuplicable *instance, gpointer user_data );
+static void           release_signal_consumers( GList *consumers );
+
 GType
 na_iduplicable_get_type( void )
 {
@@ -124,17 +132,38 @@ interface_base_init( NAIDuplicableInterface *klass )
 
 		klass->private = g_new0( NAIDuplicableInterfacePrivate, 1 );
 
+		klass->private->consumers = NULL;
+
 		/**
 		 * na-iduplicable-modified-changed:
 		 *
-		 * This signal is emitted byIDuplicable when the modification
+		 * This signal is emitted by NAIDuplicable when the modification
 		 * status of an object has been modified.
 		 */
-		st_signals[ MODIFIED_CHANGED ] = g_signal_new(
+		st_signals[ MODIFIED_CHANGED ] = g_signal_new_class_handler(
 				NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED,
 				G_TYPE_OBJECT,
 				G_SIGNAL_RUN_LAST,
-				0,
+				( GCallback ) propagate_modified_changed,
+				NULL,
+				NULL,
+				g_cclosure_marshal_VOID__POINTER,
+				G_TYPE_NONE,
+				1,
+				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,
@@ -148,11 +177,11 @@ interface_base_init( NAIDuplicableInterface *klass )
 		 * This signal is emitted byIDuplicable when the validity
 		 * status of an object has been modified.
 		 */
-		st_signals[ VALID_CHANGED ] = g_signal_new(
+		st_signals[ VALID_CHANGED ] = g_signal_new_class_handler(
 				NA_IDUPLICABLE_SIGNAL_VALID_CHANGED,
 				G_TYPE_OBJECT,
 				G_SIGNAL_RUN_LAST,
-				0,
+				( GCallback ) propagate_valid_changed,
 				NULL,
 				NULL,
 				g_cclosure_marshal_VOID__POINTER,
@@ -160,6 +189,27 @@ 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;
 	}
 }
@@ -175,6 +225,8 @@ interface_base_finalize( NAIDuplicableInterface *klass )
 
 		g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
 
+		release_signal_consumers( klass->private->consumers );
+
 		g_free( klass->private );
 	}
 }
@@ -404,6 +456,23 @@ na_iduplicable_set_origin( NAIDuplicable *object, const NAIDuplicable *origin )
 	set_origin( object, origin );
 }
 
+/**
+ * na_iduplicable_register_consumer:
+ * @consumer: the target instance.
+ *
+ * This function registers a consumer, i.e. an instance to which edition
+ * status signals will be propagated.
+ */
+void
+na_iduplicable_register_consumer( GObject *consumer )
+{
+	if( st_initialized && !st_finalized ){
+		g_return_if_fail( st_interface );
+		g_debug( "na_iduplicable_register_consumer: consumer=%p", ( void * ) consumer );
+		st_interface->private->consumers = g_list_prepend( st_interface->private->consumers, consumer );
+	}
+}
+
 static NAIDuplicable *
 v_new( const NAIDuplicable *object )
 {
@@ -507,3 +576,42 @@ set_valid( const NAIDuplicable *object, gboolean is_valid )
 #endif
 	}
 }
+
+static void
+propagate_modified_changed( NAIDuplicable *instance, gpointer user_data )
+{
+	/*g_debug( "na_iduplicable_propagate_modified_changed: instance=%p (%s), user_data=%p (%s)",
+			( 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 );
+}
+
+static void
+propagate_valid_changed( NAIDuplicable *instance, gpointer user_data )
+{
+	/*g_debug( "na_iduplicable_propagate_valid_changed: instance=%p (%s), user_data=%p (%s)",
+			( 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 );
+}
+
+static void
+propagate_signal_to_consumers( const gchar *signal, NAIDuplicable *instance, gpointer user_data )
+{
+	GList *ic;
+
+	if( st_initialized && !st_finalized ){
+		g_return_if_fail( st_interface );
+		for( ic = st_interface->private->consumers ; ic ; ic = ic->next ){
+			g_signal_emit_by_name( ic->data, signal, user_data );
+		}
+	}
+}
+
+static void
+release_signal_consumers( GList *consumers )
+{
+	g_list_free( consumers );
+}
diff --git a/src/common/na-iduplicable.h b/src/common/na-iduplicable.h
index 920993f..7605e75 100644
--- a/src/common/na-iduplicable.h
+++ b/src/common/na-iduplicable.h
@@ -142,10 +142,12 @@ typedef struct {
 }
 	NAIDuplicableInterface;
 
-#define NA_IDUPLICABLE_SIGNAL_MODIFIED_CHANGED	"na-iduplicable-modified-changed"
-#define NA_IDUPLICABLE_SIGNAL_VALID_CHANGED		"na-iduplicable-valid-changed"
+#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_EDITION_STATUS_DEBUG		0
+#define NA_IDUPLICABLE_EDITION_STATUS_DEBUG				0
 
 GType          na_iduplicable_get_type( void );
 
@@ -162,6 +164,8 @@ NAIDuplicable *na_iduplicable_get_origin( const NAIDuplicable *object );
 
 void           na_iduplicable_set_origin( NAIDuplicable *object, const NAIDuplicable *origin );
 
+void           na_iduplicable_register_consumer( GObject *consumer );
+
 G_END_DECLS
 
 #endif /* __NA_IDUPLICABLE_H__ */
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 498ba94..4333770 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -35,6 +35,7 @@
 #include <gdk/gdkkeysyms.h>
 #include <string.h>
 
+#include <common/na-iduplicable.h>
 #include <common/na-object-api.h>
 #include <common/na-object-action.h>
 #include <common/na-object-menu.h>
@@ -126,6 +127,7 @@ static void         iter_on_selection( NactIActionsList *instance, FnIterOnSelec
 static GtkTreePath *object_to_path( NactIActionsList *instance, NactTreeModel *model, NAObject *object );
 static gboolean     object_to_path_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ObjectToPathIter *otp );
 static gboolean     on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsList *instance );
+static void         on_edition_status_changed( NactIActionsList *instance, NAIDuplicable *object );
 static gboolean     on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *instance );
 static void         on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance );
 static void         on_iactions_list_item_updated( NactIActionsList *instance, NAObject *object );
@@ -403,6 +405,22 @@ nact_iactions_list_runtime_init_toplevel( NactIActionsList *instance, GList *ite
 	 * 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 ));
 }
 
 /**
@@ -473,7 +491,7 @@ nact_iactions_list_delete_selection( NactIActionsList *instance )
 	g_list_free( selected );
 
 	if( path ){
-		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, path );
 		gtk_tree_path_free( path );
 	}
@@ -687,7 +705,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 );
@@ -1247,6 +1265,25 @@ on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsLis
 	return( stop );
 }
 
+static void
+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)",
+			( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
+			( void * ) object, G_OBJECT_TYPE_NAME( object ));*/
+
+	if( is_selection_changed_authorized( instance )){
+		g_return_if_fail( NA_IS_OBJECT( object ));
+
+		treeview = get_actions_list_treeview( instance );
+		model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+		nact_tree_model_display( model, NA_OBJECT( object ));
+	}
+}
+
 static gboolean
 on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *instance )
 {
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index f21c470..e82836b 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -501,6 +501,7 @@ nact_tree_model_display( NactTreeModel *model, NAObject *object )
 {
 	GtkTreeStore *store;
 	GtkTreeIter iter;
+	GtkTreePath *path;
 
 	store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
 
@@ -508,7 +509,10 @@ nact_tree_model_display( NactTreeModel *model, NAObject *object )
 		display_item( store, model->private->treeview, &iter, object );
 	}
 
-	gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
+	/*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



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