[nautilus-actions] Fix a memory leak when removing items from the tree store
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Fix a memory leak when removing items from the tree store
- Date: Sat, 26 Sep 2009 22:50:36 +0000 (UTC)
commit 76ed9812cb3b898e14466c70ff765272c14d8a9c
Author: Pierre Wieser <pwieser trychlos org>
Date: Sun Sep 27 00:23:20 2009 +0200
Fix a memory leak when removing items from the tree store
src/common/na-object-class.h | 1 -
src/common/na-object-item.c | 8 +++--
src/common/na-object.c | 1 -
src/nact/nact-iactions-list.c | 32 +++++++++++----------
src/nact/nact-iactions-list.h | 2 +-
src/nact/nact-main-menubar.c | 8 ++++-
src/nact/nact-main-window.c | 9 ++++++
src/nact/nact-tree-model.c | 63 ++++++++++++++++++++++++----------------
src/nact/nact-tree-model.h | 24 ++++++++--------
9 files changed, 88 insertions(+), 60 deletions(-)
---
diff --git a/src/common/na-object-class.h b/src/common/na-object-class.h
index 5d0b018..07506b8 100644
--- a/src/common/na-object-class.h
+++ b/src/common/na-object-class.h
@@ -97,7 +97,6 @@ typedef struct {
gchar * ( *get_clipboard_id )( const NAObject *object );
/**
- * TODO: get ride of this
* ref:
* @object: the #NAObject-derived object to be reffed.
*
diff --git a/src/common/na-object-item.c b/src/common/na-object-item.c
index 9053233..211d026 100644
--- a/src/common/na-object-item.c
+++ b/src/common/na-object-item.c
@@ -589,6 +589,8 @@ na_object_item_free_items( GList *items )
for( it = items ; it ; it = it->next ){
if( G_IS_OBJECT( it->data )){
g_object_unref( it->data );
+ } else {
+ g_warning( "na_object_item_free_items: %p not an object", ( void * ) it->data );
}
}
@@ -734,7 +736,7 @@ na_object_item_set_items( NAObjectItem *item, GList *items )
*
* Appends a new @object to the list of subitems of @item.
*
- * We add a reference on provided @object.
+ * Doesn't modify the reference count on @object.
*/
void
na_object_item_append_item( NAObjectItem *item, const NAObject *object )
@@ -758,7 +760,7 @@ na_object_item_append_item( NAObjectItem *item, const NAObject *object )
*
* Inserts a new @object in the list of subitems of @item.
*
- * We add a reference on provided @object.
+ * Doesn't modify the reference count on @object.
*/
void
na_object_item_insert_item( NAObjectItem *item, const NAObject *object, const NAObject *before )
@@ -789,7 +791,7 @@ na_object_item_insert_item( NAObjectItem *item, const NAObject *object, const NA
*
* Removes an @object from the list of subitems of @item.
*
- * We decrement the reference count on @object.
+ * Doesn't modify the reference count on @object.
*/
void
na_object_item_remove_item( NAObjectItem *item, const NAObject *object )
diff --git a/src/common/na-object.c b/src/common/na-object.c
index 732973d..ac6ceda 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -543,7 +543,6 @@ na_object_object_get_clipboard_id( const NAObject *object )
}
/**
- * TODO: get ride of this
* na_object_object_ref:
* @object: the #NAObject-derived object to be reffed.
*
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 05bae1b..cbda05d 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -263,6 +263,7 @@ interface_base_init( NactIActionsListInterface *klass )
static void
free_items_callback( NactIActionsList *instance, GList *items )
{
+ g_debug( "free_items_callback: selection=%p (%d items)", ( void * ) items, g_list_length( items ));
na_object_free_items( items );
}
@@ -482,45 +483,43 @@ nact_iactions_list_dispose( NactIActionsList *instance )
}
/**
- * nact_iactions_list_delete_selection:
+ * nact_iactions_list_delete:
* @window: this #NactIActionsList instance.
+ * @list: list of #NAObject to be deleted.
*
- * Deletes the current selection from the underlying tree store.
+ * Deletes the specified list from the underlying tree store.
*
* This function takes care of repositionning a new selection if
* possible, and refilter the display model.
*/
void
-nact_iactions_list_delete_selection( NactIActionsList *instance )
+nact_iactions_list_delete( NactIActionsList *instance, GList *items )
{
GtkTreeView *treeview;
GtkTreeModel *model;
- GtkTreeSelection *selection;
- GList *selected;
GtkTreePath *path = NULL;
+ GList *it;
g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
if( st_initialized && !st_finalized ){
treeview = get_actions_list_treeview( instance );
- selection = gtk_tree_view_get_selection( treeview );
- selected = gtk_tree_selection_get_selected_rows( selection, &model );
+ model = gtk_tree_view_get_model( treeview );
set_selection_changed_mode( instance, FALSE );
- if( g_list_length( selected )){
- path = gtk_tree_path_copy(( GtkTreePath * ) selected->data );
- nact_tree_model_remove( NACT_TREE_MODEL( model ), selected );
+ for( it = items ; it ; it = it->next ){
+ if( path ){
+ gtk_tree_path_free( path );
+ }
+ path = nact_tree_model_remove( NACT_TREE_MODEL( model ), NA_OBJECT( it->data ));
}
set_selection_changed_mode( instance, TRUE );
-
- g_list_foreach( selected, ( GFunc ) gtk_tree_path_free, NULL );
- g_list_free( selected );
+ gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
if( path ){
- gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
select_row_at_path( instance, treeview, model, path );
gtk_tree_path_free( path );
}
@@ -1431,10 +1430,13 @@ on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *in
GList *selected_items;
selected_items = nact_iactions_list_get_selected_items( instance );
+ g_debug( "on_treeview_selection_changed: selection=%p (%d items)", ( void * ) selected_items, g_list_length( selected_items ));
if( is_selection_changed_authorized( instance )){
g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_SELECTION_CHANGED, selected_items );
}
+
+ /* selection list if free in cleanup handler for the signal */
}
/*
@@ -1512,7 +1514,7 @@ select_first_row( NactIActionsList *instance )
* @window: this #NactIActionsList instance.
* @path: a #GtkTreePath.
*
- * Select the rows at the required path, or the next following, or
+ * Select the row at the required path, or the next following, or
* the immediate previous.
*/
static void
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index f1e4628..accf080 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -94,7 +94,7 @@ void nact_iactions_list_runtime_init_toplevel( NactIActionsList *instance,
void nact_iactions_list_all_widgets_showed( NactIActionsList *instance );
void nact_iactions_list_dispose( NactIActionsList *instance );
-void nact_iactions_list_delete_selection( NactIActionsList *instance );
+void nact_iactions_list_delete( NactIActionsList *instance, GList *items );
void nact_iactions_list_fill( NactIActionsList *instance, GList *items );
NAObject *nact_iactions_list_get_item( NactIActionsList *instance, const gchar *uuid );
GList *nact_iactions_list_get_items( NactIActionsList *instance );
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
index ec79c71..3ddfbfd 100644
--- a/src/nact/nact-main-menubar.c
+++ b/src/nact/nact-main-menubar.c
@@ -489,7 +489,7 @@ on_cut_activated( GtkAction *gtk_action, NactMainWindow *window )
items = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window ));
nact_main_window_move_to_deleted( window, items );
nact_clipboard_primary_set( items, FALSE );
- nact_iactions_list_delete_selection( NACT_IACTIONS_LIST( window ));
+ nact_iactions_list_delete( NACT_IACTIONS_LIST( window ), items );
/* do not unref selected items as the ref has been moved to main_deleted
*/
@@ -584,13 +584,17 @@ static void
on_delete_activated( GtkAction *gtk_action, NactMainWindow *window )
{
GList *items;
+ GList *it;
g_return_if_fail( GTK_IS_ACTION( gtk_action ));
g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
items = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window ));
+ for( it = items ; it ; it = it->next ){
+ g_debug( "on_delete_activated: items=%p (%s)", ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ));
+ }
nact_main_window_move_to_deleted( window, items );
- nact_iactions_list_delete_selection( NACT_IACTIONS_LIST( window ));
+ nact_iactions_list_delete( NACT_IACTIONS_LIST( window ), items );
/* do not unref selected items as the ref has been moved to main_deleted
*/
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index ce652e8..d535e9c 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -492,6 +492,7 @@ instance_dispose( GObject *window )
NactMainWindow *self;
GtkWidget *pane;
gint pos;
+ GList *it;
g_debug( "%s: window=%p", thisfn, ( void * ) window );
g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
@@ -507,6 +508,9 @@ instance_dispose( GObject *window )
pos = gtk_paned_get_position( GTK_PANED( pane ));
base_iprefs_set_int( BASE_WINDOW( window ), "main-paned", pos );
+ for( it = self->private->deleted ; it ; it = it->next ){
+ g_debug( "nact_main_window_instance_dispose: %p (%s)", ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ));
+ }
na_object_free_items( self->private->deleted );
nact_iactions_list_dispose( NACT_IACTIONS_LIST( window ));
@@ -647,10 +651,15 @@ nact_main_window_has_modified_items( const NactMainWindow *window )
void
nact_main_window_move_to_deleted( NactMainWindow *window, GList *items )
{
+ GList *it;
+
g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
if( !window->private->dispose_has_run ){
window->private->deleted = g_list_concat( window->private->deleted, items );
+ for( it = window->private->deleted ; it ; it = it->next ){
+ g_debug( "nact_main_window_move_to_deleted: %p (%s)", ( void * ) it->data, G_OBJECT_TYPE_NAME( it->data ));
+ }
}
}
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index 045c579..b1231e9 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -164,12 +164,13 @@ static void insert_before_parent_get_iters( GtkTreeModel *model, GtkT
static void insert_as_last_child_get_iters( GtkTreeModel *model, GtkTreePath *select_path, const NAObject *object, GtkTreeIter *parent_iter, gboolean *has_parent_iter, GtkTreeIter *sibling_iter, gboolean *has_sibling_iter, NAObject **parent_object );
static void remove_if_exists( NactTreeModel *model, GtkTreeModel *store, const NAObject *object );
-static GList *add_parent( GList *parents, GtkTreeModel *store, GtkTreeIter *obj_iter, GtkTreePath *obj_path );
+static GList *add_parent( GList *parents, GtkTreeModel *store, GtkTreeIter *obj_iter );
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 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 gboolean remove_items( GtkTreeStore *store, GtkTreeIter *iter );
static gboolean search_for_object( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *iter );
static gboolean search_for_objet_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmSearchStruct *ntm );
static gboolean search_for_object_id( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *iter );
@@ -936,54 +937,48 @@ nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data
/**
* nact_tree_model_remove:
* @model: this #NactTreeModel instance.
- * @selected: a list of #GtkTreePath as returned by
- * gtk_tree_selection_get_selected_rows().
+ * @object: the #NAObject to be deleted.
*
- * Deletes the selected rows, unref-ing the underlying objects if any.
+ * Recursively deletes the specified object.
*
- * We begin by the end, so that we are almost sure that path remain
- * valid during the iteration.
+ * Returns: a path which may be suitable for the next selection.
*/
-void
-nact_tree_model_remove( NactTreeModel *model, GList *selected )
+GtkTreePath *
+nact_tree_model_remove( NactTreeModel *model, NAObject *object )
{
- GList *reversed, *it;
GtkTreeIter iter;
GtkTreeStore *store;
- gchar *path_str;
GList *parents = NULL;
+ GList *it;
+ GtkTreePath *path = NULL;
- g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+ g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), NULL );
if( !model->private->dispose_has_run ){
- reversed = g_list_reverse( selected );
store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
- for( it = reversed ; it ; it = it->next ){
-
- path_str = gtk_tree_path_to_string(( GtkTreePath * ) it->data );
- g_debug( "nact_tree_model_remove: path=%s", path_str );
- g_free( path_str );
-
- gtk_tree_model_get_iter( GTK_TREE_MODEL( store ), &iter, ( GtkTreePath * ) it->data );
- parents = add_parent( parents, GTK_TREE_MODEL( store ), &iter, ( GtkTreePath * ) it->data );
- gtk_tree_store_remove( store, &iter );
+ if( search_for_object( model, GTK_TREE_MODEL( store ), object, &iter )){
+ parents = add_parent( parents, GTK_TREE_MODEL( store ), &iter );
+ path = gtk_tree_model_get_path( GTK_TREE_MODEL( store ), &iter );
+ remove_items( store, &iter );
}
for( it = parents ; it ; it = it->next ){
na_object_check_edition_status( it->data );
}
}
+
+ return( path );
}
/*
- * iter and path are positionned on the row which is going to be deleted
+ * iter is positionned on the row which is going to be deleted
* remove the object from the subitems list of parent (if any)
* add parent to the list to check its status after remove will be done
*/
static GList *
-add_parent( GList *parents, GtkTreeModel *store, GtkTreeIter *obj_iter, GtkTreePath *obj_path )
+add_parent( GList *parents, GtkTreeModel *store, GtkTreeIter *obj_iter )
{
NAObject *object;
GtkTreePath *path;
@@ -991,7 +986,7 @@ add_parent( GList *parents, GtkTreeModel *store, GtkTreeIter *obj_iter, GtkTreeP
NAObject *parent;
gtk_tree_model_get( store, obj_iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
- path = gtk_tree_path_copy( obj_path );
+ path = gtk_tree_model_get_path( store, obj_iter );
if( gtk_tree_path_get_depth( path ) > 1 ){
gtk_tree_path_up( path );
@@ -1098,6 +1093,24 @@ iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter
return( stop );
}
+/*
+ * recursively remove child items starting with iter
+ * returns TRUE if iter is always valid after the remove
+ */
+static gboolean
+remove_items( GtkTreeStore *store, GtkTreeIter *iter )
+{
+ GtkTreeIter child;
+ gboolean valid;
+
+ while( gtk_tree_model_iter_children( GTK_TREE_MODEL( store ), &child, iter )){
+ remove_items( store, &child );
+ }
+ valid = gtk_tree_store_remove( store, iter );
+
+ return( valid );
+}
+
static gboolean
search_for_object( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *result_iter )
{
@@ -1303,7 +1316,7 @@ imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source,
break;
}
- g_list_free( selected_items );
+ na_object_free_items( selected_items );
return( ret );
}
diff --git a/src/nact/nact-tree-model.h b/src/nact/nact-tree-model.h
index 1ac9009..c4ca015 100644
--- a/src/nact/nact-tree-model.h
+++ b/src/nact/nact-tree-model.h
@@ -87,18 +87,18 @@ enum {
*/
typedef gboolean ( *FnIterOnStore )( NactTreeModel *, GtkTreePath *, NAObject *, gpointer );
-GType nact_tree_model_get_type( void );
-
-void nact_tree_model_initial_load( BaseWindow *window, GtkTreeView *treeview );
-void nact_tree_model_runtime_init( NactTreeModel *model, gboolean have_dnd );
-void nact_tree_model_dispose( NactTreeModel *model );
-
-void nact_tree_model_display( NactTreeModel *model, NAObject *object );
-void nact_tree_model_dump( NactTreeModel *model );
-void nact_tree_model_fill( NactTreeModel *model, GList *items, gboolean only_actions);
-gchar *nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent );
-void nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data );
-void nact_tree_model_remove( NactTreeModel *model, GList *selected );
+GType nact_tree_model_get_type( void );
+
+void nact_tree_model_initial_load( BaseWindow *window, GtkTreeView *treeview );
+void nact_tree_model_runtime_init( NactTreeModel *model, gboolean have_dnd );
+void nact_tree_model_dispose( NactTreeModel *model );
+
+void nact_tree_model_display( NactTreeModel *model, NAObject *object );
+void nact_tree_model_dump( NactTreeModel *model );
+void nact_tree_model_fill( NactTreeModel *model, GList *items, gboolean only_actions);
+gchar *nact_tree_model_insert( NactTreeModel *model, const NAObject *object, GtkTreePath *path, NAObject **parent );
+void nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data );
+GtkTreePath *nact_tree_model_remove( NactTreeModel *model, NAObject *object );
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]