[nautilus-actions] Update action sensitivites on item status changed



commit 60ad1c3009b62855728414c2c29171588de0a166
Author: pierre <pierre vfedora10 virtuals pwi>
Date:   Wed Oct 14 14:30:39 2009 +0200

    Update action sensitivites on item status changed
    
    Fix update of origin in pivot when saving a subitem.

 ChangeLog                       |   12 ++++++
 src/nact/nact-iactions-list.c   |   78 +++++++++++++++++++++++++++++++++++---
 src/nact/nact-iactions-list.h   |    2 +
 src/nact/nact-main-menubar.c    |   47 ++++++++++++++++++-----
 src/runtime/na-gconf-provider.c |    9 +++-
 src/runtime/na-object-id.c      |    6 +--
 src/runtime/na-object-item.c    |   14 ++++++-
 src/runtime/na-pivot.c          |    2 +-
 8 files changed, 143 insertions(+), 27 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 64428dd..58e07cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-10-14 Pierre Wieser <pwieser trychlos org>
+
+	* src/nact/nact-iactions-list.c:
+	Maintains a list of modified items, cleared when saving.
+	Define a new "status-changed" signal.
+
+	* src/nact/nact-main-menubar.c:
+	Update action sensitivities when a status is changed.
+
+	* src/runtime/na-gconf-provider.c:
+	Manage unknown types.
+
 2009-10-13 Pierre Wieser <pwieser trychlos org>
 
 	* src/runtime/na-iduplicable.c:
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 307d62b..6019bac 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -70,6 +70,13 @@ typedef struct {
 	 */
 	gulong   tab_updated_handler;
 	gboolean selection_changed_send_allowed;
+
+	/* maintains a flat list of modified objects
+	 * should be faster than iterating each time this is needed
+	 * not very reliable as not all deleted items are removed from it
+	 * but enough to enable/disable save
+	 */
+	GList   *modified_items;
 }
 	IActionsListInstanceData;
 
@@ -83,6 +90,7 @@ enum {
 	FOCUS_IN,
 	FOCUS_OUT,
 	COLUMN_EDITED,
+	STATUS_CHANGED,
 	LAST_SIGNAL
 };
 
@@ -153,7 +161,7 @@ static void         filter_selection_iter( GtkTreeModel *model, GtkTreePath *pat
 static GtkTreeView *get_actions_list_treeview( NactIActionsList *instance );
 static gboolean     get_item_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, IdToObjectIter *ito );
 static gboolean     get_items_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList **items );
-static gboolean     has_modified_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, gboolean *has_modified );
+/*static gboolean     has_modified_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, gboolean *has_modified );*/
 static gboolean     have_dnd_mode( NactIActionsList *instance, IActionsListInstanceData *ialid );
 static gboolean     have_filter_selection_mode( NactIActionsList *instance, IActionsListInstanceData *ialid );
 static gboolean     have_only_actions( NactIActionsList *instance, IActionsListInstanceData *ialid );
@@ -339,6 +347,24 @@ interface_base_init( NactIActionsListInterface *klass )
 				G_TYPE_POINTER,
 				G_TYPE_INT );
 
+		/**
+		 * nact-iactions-list-status-changed:
+		 *
+		 * This signal is emitted byIActionsList to its implementor
+		 * when the status of an item is changed.
+		 */
+		st_signals[ STATUS_CHANGED ] = g_signal_new(
+				IACTIONS_LIST_SIGNAL_STATUS_CHANGED,
+				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_initialized = TRUE;
 	}
 }
@@ -691,6 +717,8 @@ nact_iactions_list_delete( NactIActionsList *instance, GList *items )
 
 			path = nact_tree_model_remove( NACT_TREE_MODEL( model ), NA_OBJECT( it->data ));
 
+			ialid->modified_items = g_list_remove( ialid->modified_items, it->data );
+
 			g_debug( "%s: object=%p (%s, ref_count=%d)", thisfn,
 					( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ), G_OBJECT( it->data )->ref_count );
 		}
@@ -966,17 +994,20 @@ gboolean
 nact_iactions_list_has_modified_items( NactIActionsList *instance )
 {
 	gboolean has_modified = FALSE;
-	GtkTreeView *treeview;
-	NactTreeModel *model;
+	/*GtkTreeView *treeview;
+	NactTreeModel *model;*/
+	IActionsListInstanceData *ialid;
 
 	g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), FALSE );
 
 	if( st_initialized && !st_finalized ){
 
-		treeview = get_actions_list_treeview( instance );
-		model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+		ialid = get_instance_data( instance );
+		has_modified = ( g_list_length( ialid->modified_items ) > 0 );
 
-		nact_tree_model_iter( model, ( FnIterOnStore ) has_modified_iter, &has_modified );
+		/*treeview = get_actions_list_treeview( instance );
+		model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+		nact_tree_model_iter( model, ( FnIterOnStore ) has_modified_iter, &has_modified );*/
 	}
 
 	return( has_modified );
@@ -1359,6 +1390,27 @@ nact_iactions_list_is_expanded( NactIActionsList *instance, const NAObject *item
 }
 
 /**
+ * nact_iactions_list_removed_modified:
+ * @instance: this #NactIActionsList instance.
+ *
+ * Clears the modified items list.
+ */
+void
+nact_iactions_list_removed_modified( NactIActionsList *instance )
+{
+	IActionsListInstanceData *ialid;
+
+	g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
+
+	if( st_initialized && !st_finalized ){
+
+		ialid = get_instance_data( instance );
+		g_list_free( ialid->modified_items );
+		ialid->modified_items = NULL;
+	}
+}
+
+/**
  * nact_iactions_list_set_management_mode:
  * @instance: this #NactIActionsList instance.
  * @mode: management mode.
@@ -1662,6 +1714,7 @@ get_items_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, GList
 /*
  * stop as soon as we have found a modified item
  */
+#if 0
 static gboolean
 has_modified_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, gboolean *has_modified )
 {
@@ -1673,6 +1726,7 @@ has_modified_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, gb
 	/* don't stop iteration if not modified */
 	return( FALSE );
 }
+#endif
 
 static gboolean
 have_dnd_mode( NactIActionsList *instance, IActionsListInstanceData *ialid )
@@ -1804,7 +1858,7 @@ on_edition_status_changed( NactIActionsList *instance, NAIDuplicable *object )
 	IActionsListInstanceData *ialid;
 
 	ialid = get_instance_data( instance );
-	if( ialid->selection_changed_send_allowed ){
+	/*if( ialid->selection_changed_send_allowed ){*/
 
 		g_debug( "nact_iactions_list_on_edition_status_changed: instance=%p, object=%p (%s)",
 				( void * ) instance,
@@ -1815,7 +1869,17 @@ on_edition_status_changed( NactIActionsList *instance, NAIDuplicable *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 ));
+	/*}*/
+
+	if( na_object_is_modified( object )){
+		if( !g_list_find( ialid->modified_items, object )){
+			ialid->modified_items = g_list_prepend( ialid->modified_items, object );
+		}
+	} else {
+		ialid->modified_items = g_list_remove( ialid->modified_items, object );
 	}
+
+	g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_STATUS_CHANGED, NULL );
 }
 
 static gboolean
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index f8c0347..2850bcd 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -108,6 +108,7 @@ typedef struct {
 #define IACTIONS_LIST_SIGNAL_FOCUS_IN					"nact-iactions-list-focus-in"
 #define IACTIONS_LIST_SIGNAL_FOCUS_OUT					"nact-iactions-list-focus-out"
 #define IACTIONS_LIST_SIGNAL_COLUMN_EDITED				"nact-iactions-list-column-edited"
+#define IACTIONS_LIST_SIGNAL_STATUS_CHANGED				"nact-iactions-list-status-changed"
 
 /* management modes
  * - edition: dnd, filter, multiple selection, item updated signal
@@ -140,6 +141,7 @@ void      nact_iactions_list_insert_at_path( NactIActionsList *instance, GList *
 void      nact_iactions_list_insert_items( NactIActionsList *instance, GList *items, NAObject *sibling );
 void      nact_iactions_list_insert_into( NactIActionsList *instance, GList *items );
 gboolean  nact_iactions_list_is_expanded( NactIActionsList *instance, const NAObject *item );
+void      nact_iactions_list_removed_modified( NactIActionsList *instance );
 void      nact_iactions_list_set_management_mode( NactIActionsList *instance, gint mode );
 void      nact_iactions_list_toggle_collapse( NactIActionsList *instance, const NAObject *item );
 
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index b78bf57..a03308a 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -94,6 +94,7 @@ static void     on_iactions_list_count_updated( NactMainWindow *window, gint men
 static void     on_iactions_list_selection_changed( NactMainWindow *window, GList *selected );
 static void     on_iactions_list_focus_in( NactMainWindow *window, gpointer user_data );
 static void     on_iactions_list_focus_out( NactMainWindow *window, gpointer user_data );
+static void     on_iactions_list_status_changed( NactMainWindow *window, gpointer user_data );
 static void     on_level_zero_order_changed( NactMainWindow *window, gpointer user_data );
 static void     on_update_sensitivities( NactMainWindow *window, gpointer user_data );
 
@@ -350,6 +351,12 @@ nact_main_menubar_runtime_init( NactMainWindow *window )
 	base_window_signal_connect(
 			BASE_WINDOW( window ),
 			G_OBJECT( window ),
+			IACTIONS_LIST_SIGNAL_STATUS_CHANGED,
+			G_CALLBACK( on_iactions_list_status_changed ));
+
+	base_window_signal_connect(
+			BASE_WINDOW( window ),
+			G_OBJECT( window ),
 			MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES,
 			G_CALLBACK( on_update_sensitivities ));
 
@@ -453,6 +460,15 @@ on_iactions_list_focus_out( NactMainWindow *window, gpointer user_data )
 }
 
 static void
+on_iactions_list_status_changed( NactMainWindow *window, gpointer user_data )
+{
+	g_debug( "nact_main_menubar_on_iactions_list_status_changed" );
+	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+	g_signal_emit_by_name( window, MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES, NULL );
+}
+
+static void
 on_level_zero_order_changed( NactMainWindow *window, gpointer user_data )
 {
 	MenubarIndicatorsStruct *mis;
@@ -674,7 +690,12 @@ on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
 	items = nact_iactions_list_get_items( NACT_IACTIONS_LIST( window ));
 	na_pivot_write_level_zero( pivot, items );
 
+	/* remove modified items
+	 */
+	nact_iactions_list_removed_modified( NACT_IACTIONS_LIST( window ));
+
 	/* recursively save the modified items
+	 * check is useless here if item was not modified, but not very costly
 	 */
 	for( it = items ; it ; it = it->next ){
 		save_item( window, pivot, NA_OBJECT_ITEM( it->data ));
@@ -687,10 +708,6 @@ on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
 	mis = ( MenubarIndicatorsStruct * ) g_object_get_data( G_OBJECT( window ), MENUBAR_PROP_INDICATORS );
 	mis->level_zero_order_changed = FALSE;
 
-	/* required as selection has not changed
-	 */
-	g_signal_emit_by_name( window, MAIN_WINDOW_SIGNAL_UPDATE_ACTION_SENSITIVITIES, NULL );
-
 	/* get ride of notification messages of IOProviders
 	 */
 	na_ipivot_consumer_delay_notify( NA_IPIVOT_CONSUMER( window ));
@@ -709,6 +726,7 @@ save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
 	NAObjectItem *origin;
 	NAObjectItem *dup_pivot;
 	GList *subitems, *it;
+	NAObjectItem *parent;
 
 	g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
 	g_return_if_fail( NA_IS_PIVOT( pivot ));
@@ -721,9 +739,8 @@ save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
 		}
 	}
 
-	if( na_object_is_modified( item )){
-
-		if( nact_window_save_item( NACT_WINDOW( window ), item )){
+	if( na_object_is_modified( item ) &&
+		nact_window_save_item( NACT_WINDOW( window ), item )){
 
 			if( NA_IS_OBJECT_ACTION( item )){
 				na_object_action_reset_last_allocated( NA_OBJECT_ACTION( item ));
@@ -733,15 +750,25 @@ save_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *item )
 			 * (valid) NULL value
 			 */
 			origin = ( NAObjectItem * ) na_object_get_origin( item );
+			parent = NULL;
 
 			if( origin ){
-				na_pivot_remove_item( pivot, NA_OBJECT( origin ));
+				parent = na_object_get_parent( origin );
+				if( parent ){
+					na_object_remove_item( parent, origin );
+				} else {
+					na_pivot_remove_item( pivot, NA_OBJECT( origin ));
+				}
 			}
 
 			dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( item ));
 			na_object_reset_origin( item, dup_pivot );
-			na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
-		}
+			na_object_set_parent( dup_pivot, parent );
+			if( parent ){
+				na_object_append_item( parent, dup_pivot );
+			} else {
+				na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
+			}
 	}
 }
 
diff --git a/src/runtime/na-gconf-provider.c b/src/runtime/na-gconf-provider.c
index 869f2e8..16cb920 100644
--- a/src/runtime/na-gconf-provider.c
+++ b/src/runtime/na-gconf-provider.c
@@ -450,7 +450,9 @@ iio_provider_read_items_list( const NAIIOProvider *provider )
 
 			const gchar *path = ( const gchar * ) ip->data;
 			item = read_item( self, path );
-			items_list = g_list_prepend( items_list, item );
+			if( item ){
+				items_list = g_list_prepend( items_list, item );
+			}
 		}
 
 		na_gconf_utils_free_subdirs( listpath );
@@ -477,14 +479,15 @@ read_item( NAGConfProvider *provider, const gchar *path )
 	full_path = gconf_concat_dir_and_key( path, OBJECT_ITEM_TYPE_ENTRY );
 	type = na_gconf_utils_read_string( provider->private->gconf, full_path, TRUE, OBJECT_ITEM_TYPE_ACTION );
 	g_free( full_path );
+	item = NULL;
 
-	/* a menu has a 'type' = 'menu'
+	/* a menu has a type='Menu'
 	 */
 	if( have_type && !strcmp( type, OBJECT_ITEM_TYPE_MENU )){
 		item = NA_OBJECT_ITEM( na_object_menu_new());
 		read_item_menu( provider, path, NA_OBJECT_MENU( item ));
 
-	/* else this should be an action (no type, or 'type' = 'action')
+	/* else this should be an action (no type, or type='Action')
 	 */
 	} else if( !have_type || !strcmp( type, OBJECT_ITEM_TYPE_ACTION )){
 		item = NA_OBJECT_ITEM( na_object_action_new());
diff --git a/src/runtime/na-object-id.c b/src/runtime/na-object-id.c
index cdab39d..62bce21 100644
--- a/src/runtime/na-object-id.c
+++ b/src/runtime/na-object-id.c
@@ -494,12 +494,10 @@ object_are_equal( const NAObject *a, const NAObject *b )
 				}
 			}
 
-#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
-			g_debug( "na_object_id_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
+			/*g_debug( "na_object_id_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
 					( void * ) a, G_OBJECT_TYPE_NAME( a ),
 					( void * ) b, G_OBJECT_TYPE_NAME( b ),
-					equal ? "True":"False" );
-#endif
+					equal ? "True":"False" );*/
 	}
 
 	return( equal );
diff --git a/src/runtime/na-object-item.c b/src/runtime/na-object-item.c
index 4c0d478..45c9beb 100644
--- a/src/runtime/na-object-item.c
+++ b/src/runtime/na-object-item.c
@@ -849,15 +849,24 @@ object_are_equal( const NAObject *a, const NAObject *b )
 			equal =
 				( g_utf8_collate( NA_OBJECT_ITEM( a )->private->tooltip, NA_OBJECT_ITEM( b )->private->tooltip ) == 0 ) &&
 				( g_utf8_collate( NA_OBJECT_ITEM( a )->private->icon, NA_OBJECT_ITEM( b )->private->icon ) == 0 );
+			/*if( !equal ){
+				g_debug( "tooltip or icon" );
+			}*/
 		}
 
 		if( equal ){
 			equal = ( NA_OBJECT_ITEM( a )->private->enabled && NA_OBJECT_ITEM( b )->private->enabled ) ||
 					( !NA_OBJECT_ITEM( a )->private->enabled && !NA_OBJECT_ITEM( b )->private->enabled );
+			/*if( !equal ){
+				g_debug( "enabled" );
+			}*/
 		}
 
 		if( equal ){
 			equal = ( g_list_length( NA_OBJECT_ITEM( a )->private->items ) == g_list_length( NA_OBJECT_ITEM( b )->private->items ));
+			if( !equal ){
+				g_debug( "length: a=%d, b=%d", g_list_length( NA_OBJECT_ITEM( a )->private->items ), g_list_length( NA_OBJECT_ITEM( b )->private->items ));
+			}
 		}
 
 		if( equal ){
@@ -873,12 +882,14 @@ object_are_equal( const NAObject *a, const NAObject *b )
 #endif
 					if( first_pos != second_pos ){
 						equal = FALSE;
+						/*g_debug( "first_id=%s, first_pos=%d, second_pos=%d", first_id, first_pos, second_pos );*/
 					}
 				} else {
 #if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
 					g_debug( "na_object_item_object_are_equal: id=%s not found in b", first_id );
 #endif
 					equal = FALSE;
+					/*g_debug( "first_id=%s, second not found", first_id );*/
 				}
 				g_free( first_id );
 			}
@@ -893,17 +904,16 @@ object_are_equal( const NAObject *a, const NAObject *b )
 					g_debug( "na_object_item_object_are_equal: id=%s not found in a", second_id );
 #endif
 					equal = FALSE;
+					/*g_debug( "second_id=%s, first not found", second_id );*/
 				}
 				g_free( second_id );
 			}
 		}
 
-#if NA_IDUPLICABLE_EDITION_STATUS_DEBUG
 		g_debug( "na_object_item_object_are_equal: a=%p (%s), b=%p (%s), are_equal=%s",
 				( void * ) a, G_OBJECT_TYPE_NAME( a ),
 				( void * ) b, G_OBJECT_TYPE_NAME( b ),
 				equal ? "True":"False" );
-#endif
 	}
 
 	return( equal );
diff --git a/src/runtime/na-pivot.c b/src/runtime/na-pivot.c
index 324031d..72c5b1d 100644
--- a/src/runtime/na-pivot.c
+++ b/src/runtime/na-pivot.c
@@ -503,7 +503,7 @@ na_pivot_remove_item( NAPivot *pivot, NAObject *item )
 {
 	g_debug( "na_pivot_remove_item: pivot=%p, item=%p (%s)",
 			( void * ) pivot,
-			( void * ) item, G_OBJECT_TYPE_NAME( item ));
+			( void * ) item, G_IS_OBJECT( item ) ? G_OBJECT_TYPE_NAME( item ) : "(null)" );
 
 	g_return_if_fail( NA_IS_PIVOT( pivot ));
 



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