app: pull more code into GimpContainerTreeStore

Keep a list of GimpCellRendererViewable around and add API to add
them. When items are removed or the store is cleared, set the
renderers' "viewable" property to NULL so they don't keep refing the
viewable.

This is not really "model" code but needs to be done for all container
views that have viewable cell renderers.

GimpContainerComboBox and GimpContainerEntry lacked that clearing, so
this change might fix some cases where objects (even images) were
removed but still stuck in memory until the model changed again.
This commit is contained in:
Michael Natterer 2010-06-03 22:09:02 +02:00
parent 6571759c43
commit 15906be4d9
5 changed files with 71 additions and 43 deletions

View File

@ -157,6 +157,9 @@ gimp_container_combo_box_init (GimpContainerComboBox *combo)
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER,
NULL);
gimp_container_tree_store_add_renderer_cell (GIMP_CONTAINER_TREE_STORE (model),
cell);
combo->viewable_renderer = cell;
cell = gtk_cell_renderer_text_new ();
@ -298,19 +301,9 @@ gimp_container_combo_box_remove_item (GimpContainerView *view,
viewable,
iter);
if (iter)
if (iter && gtk_tree_model_iter_n_children (model, NULL) == 0)
{
/* If the store is now empty, clear out renderers from all cells
* so that they don't reference the viewables. See bug #149906.
*/
if (gtk_tree_model_iter_n_children (model, NULL) == 0)
{
g_object_set (GIMP_CONTAINER_COMBO_BOX (view)->viewable_renderer,
"renderer", NULL,
NULL);
gtk_widget_set_sensitive (GTK_WIDGET (view), FALSE);
}
gtk_widget_set_sensitive (GTK_WIDGET (view), FALSE);
}
}

View File

@ -156,6 +156,9 @@ gimp_container_entry_init (GimpContainerEntry *entry)
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER,
NULL);
gimp_container_tree_store_add_renderer_cell (GIMP_CONTAINER_TREE_STORE (model),
cell);
gtk_entry_completion_set_text_column (completion,
GIMP_CONTAINER_TREE_STORE_COLUMN_NAME);

View File

@ -29,6 +29,7 @@
#include "core/gimpcontainer.h"
#include "core/gimpviewable.h"
#include "gimpcellrendererviewable.h"
#include "gimpcontainertreestore.h"
#include "gimpcontainerview.h"
#include "gimpviewrenderer.h"
@ -47,6 +48,7 @@ typedef struct _GimpContainerTreeStorePrivate GimpContainerTreeStorePrivate;
struct _GimpContainerTreeStorePrivate
{
GimpContainerView *container_view;
GList *renderer_cells;
gboolean use_name;
};
@ -131,6 +133,14 @@ gimp_container_tree_store_constructor (GType type,
static void
gimp_container_tree_store_finalize (GObject *object)
{
GimpContainerTreeStorePrivate *private = GET_PRIVATE (object);
if (private->renderer_cells)
{
g_list_free (private->renderer_cells);
private->renderer_cells = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -204,8 +214,22 @@ gimp_container_tree_store_new (GimpContainerView *container_view,
}
void
gimp_container_tree_store_set_use_name (GimpContainerTreeStore *store,
gboolean use_name)
gimp_container_tree_store_add_renderer_cell (GimpContainerTreeStore *store,
GtkCellRenderer *cell)
{
GimpContainerTreeStorePrivate *private;
g_return_if_fail (GIMP_IS_CONTAINER_TREE_STORE (store));
g_return_if_fail (GIMP_IS_CELL_RENDERER_VIEWABLE (cell));
private = GET_PRIVATE (store);
private->renderer_cells = g_list_prepend (private->renderer_cells, cell);
}
void
gimp_container_tree_store_set_use_name (GimpContainerTreeStore *store,
gboolean use_name)
{
GimpContainerTreeStorePrivate *private;
@ -285,7 +309,22 @@ gimp_container_tree_store_remove_item (GimpContainerTreeStore *store,
GtkTreeIter *iter)
{
if (iter)
gtk_tree_store_remove (GTK_TREE_STORE (store), iter);
{
gtk_tree_store_remove (GTK_TREE_STORE (store), iter);
/* If the store is empty after this remove, clear out renderers
* from all cells so they don't keep refing the viewables
* (see bug #149906).
*/
if (! gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL))
{
GimpContainerTreeStorePrivate *private = GET_PRIVATE (store);
GList *list;
for (list = private->renderer_cells; list; list = list->next)
g_object_set (list->data, "renderer", NULL, NULL);
}
}
}
void
@ -400,6 +439,19 @@ gimp_container_tree_store_clear_items (GimpContainerTreeStore *store)
g_return_if_fail (GIMP_IS_CONTAINER_TREE_STORE (store));
gtk_tree_store_clear (GTK_TREE_STORE (store));
/* If the store is empty after this remove, clear out renderers
* from all cells so they don't keep refing the viewables
* (see bug #149906).
*/
if (! gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL))
{
GimpContainerTreeStorePrivate *private = GET_PRIVATE (store);
GList *list;
for (list = private->renderer_cells; list; list = list->next)
g_object_set (list->data, "renderer", NULL, NULL);
}
}
typedef struct

View File

@ -66,6 +66,8 @@ GtkTreeModel * gimp_container_tree_store_new (GimpContainerView *
gint n_columns,
GType *types);
void gimp_container_tree_store_add_renderer_cell (GimpContainerTreeStore *store,
GtkCellRenderer *cell);
void gimp_container_tree_store_set_use_name (GimpContainerTreeStore *store,
gboolean use_name);
gboolean gimp_container_tree_store_get_use_name (GimpContainerTreeStore *store);

View File

@ -250,8 +250,8 @@ gimp_container_tree_view_constructor (GType type,
G_CALLBACK (gimp_container_tree_view_name_canceled),
tree_view);
tree_view->priv->renderer_cells = g_list_prepend (tree_view->priv->renderer_cells,
tree_view->renderer_cell);
gimp_container_tree_view_add_renderer_cell (tree_view,
tree_view->renderer_cell);
tree_view->priv->selection = gtk_tree_view_get_selection (tree_view->view);
@ -439,6 +439,9 @@ gimp_container_tree_view_add_renderer_cell (GimpContainerTreeView *tree_view,
tree_view->priv->renderer_cells = g_list_prepend (tree_view->priv->renderer_cells,
cell);
gimp_container_tree_store_add_renderer_cell (GIMP_CONTAINER_TREE_STORE (tree_view->model),
cell);
}
void
@ -596,21 +599,7 @@ gimp_container_tree_view_remove_item (GimpContainerView *view,
iter);
if (iter)
{
gtk_tree_view_columns_autosize (tree_view->view);
/* If the store is empty after this remove, clear out renderers
* from all cells so they don't keep refing the viewables
* (see bug #149906).
*/
if (! gtk_tree_model_iter_n_children (tree_view->model, NULL))
{
GList *list;
for (list = tree_view->priv->renderer_cells; list; list = list->next)
g_object_set (list->data, "renderer", NULL, NULL);
}
}
gtk_tree_view_columns_autosize (tree_view->view);
}
static void
@ -724,17 +713,6 @@ gimp_container_tree_view_clear_items (GimpContainerView *view)
gimp_container_tree_store_clear_items (GIMP_CONTAINER_TREE_STORE (tree_view->model));
/* Clear out renderers from all cells so they don't keep refing the
* viewables (see bug #149906).
*/
if (! gtk_tree_model_iter_n_children (tree_view->model, NULL))
{
GList *list;
for (list = tree_view->priv->renderer_cells; list; list = list->next)
g_object_set (list->data, "renderer", NULL, NULL);
}
parent_view_iface->clear_items (view);
}