From f3a99ed8f7311818f0ad46832e9ff1a7172c2362 Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Tue, 22 Mar 2011 23:41:42 +0100 Subject: [PATCH] app: turn GimpFilteredContainer into a general purpose filter --- app/core/gimpfilteredcontainer.c | 474 ++++++------------------------- app/core/gimpfilteredcontainer.h | 28 +- 2 files changed, 101 insertions(+), 401 deletions(-) diff --git a/app/core/gimpfilteredcontainer.c b/app/core/gimpfilteredcontainer.c index db6ddaf597..54d731bd14 100644 --- a/app/core/gimpfilteredcontainer.c +++ b/app/core/gimpfilteredcontainer.c @@ -1,9 +1,9 @@ -#if 0 /* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis * * gimpfilteredcontainer.c * Copyright (C) 2008 Aurimas Juška + * 2011 Michael Natterer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,108 +25,56 @@ #include "core-types.h" -#include "gimp.h" -#include "gimpmarshal.h" -#include "gimptag.h" -#include "gimptagged.h" #include "gimpfilteredcontainer.h" -enum -{ - TAG_COUNT_CHANGED, - LAST_SIGNAL -}; - enum { PROP_0, - PROP_SRC_CONTAINER + PROP_SRC_CONTAINER, + PROP_FILTER_FUNC, + PROP_FILTER_DATA }; -typedef struct _MatchParams -{ - GimpFilteredContainer *filtered_container; - GList *items_to_add; - GList *items_to_remove; -} MatchParams; +static void gimp_filtered_container_constructed (GObject *object); +static void gimp_filtered_container_dispose (GObject *object); +static void gimp_filtered_container_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_filtered_container_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); - -static void gimp_filtered_container_constructed (GObject *object); -static void gimp_filtered_container_dispose (GObject *object); -static void gimp_filtered_container_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_filtered_container_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static gint64 gimp_filtered_container_get_memsize (GimpObject *object, - gint64 *gui_size); - -static gboolean gimp_filtered_container_object_matches (GimpFilteredContainer *filtered_container, - GimpObject *object); - -static void gimp_filtered_container_filter (GimpFilteredContainer *filtered_container); - -static void gimp_filtered_container_src_add (GimpContainer *src_container, - GimpObject *obj, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_src_remove (GimpContainer *src_container, - GimpObject *obj, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_src_freeze (GimpContainer *src_container, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_src_thaw (GimpContainer *src_container, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_tag_added (GimpTagged *tagged, - GimpTag *tag, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_tag_removed (GimpTagged *tagged, - GimpTag *tag, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_tagged_item_added (GimpTagged *tagged, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_tagged_item_removed(GimpTagged *tagged, - GimpFilteredContainer *filtered_container); -static void gimp_filtered_container_tag_count_changed (GimpFilteredContainer *filtered_container, - gint tag_count); +static void gimp_filtered_container_filter (GimpFilteredContainer *filtered_container); +static void gimp_filtered_container_src_add (GimpContainer *src_container, + GimpObject *obj, + GimpFilteredContainer *filtered_container); +static void gimp_filtered_container_src_remove (GimpContainer *src_container, + GimpObject *obj, + GimpFilteredContainer *filtered_container); +static void gimp_filtered_container_src_freeze (GimpContainer *src_container, + GimpFilteredContainer *filtered_container); +static void gimp_filtered_container_src_thaw (GimpContainer *src_container, + GimpFilteredContainer *filtered_container); G_DEFINE_TYPE (GimpFilteredContainer, gimp_filtered_container, GIMP_TYPE_LIST) #define parent_class gimp_filtered_container_parent_class -static guint gimp_filtered_container_signals[LAST_SIGNAL] = { 0, }; - static void gimp_filtered_container_class_init (GimpFilteredContainerClass *klass) { - GObjectClass *g_object_class = G_OBJECT_CLASS (klass); - GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); + GObjectClass *g_object_class = G_OBJECT_CLASS (klass); - g_object_class->constructed = gimp_filtered_container_constructed; - g_object_class->dispose = gimp_filtered_container_dispose; - g_object_class->set_property = gimp_filtered_container_set_property; - g_object_class->get_property = gimp_filtered_container_get_property; - - gimp_object_class->get_memsize = gimp_filtered_container_get_memsize; - - klass->tag_count_changed = gimp_filtered_container_tag_count_changed; - - gimp_filtered_container_signals[TAG_COUNT_CHANGED] = - g_signal_new ("tag-count-changed", - GIMP_TYPE_FILTERED_CONTAINER, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GimpFilteredContainerClass, tag_count_changed), - NULL, NULL, - gimp_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); + g_object_class->constructed = gimp_filtered_container_constructed; + g_object_class->dispose = gimp_filtered_container_dispose; + g_object_class->set_property = gimp_filtered_container_set_property; + g_object_class->get_property = gimp_filtered_container_get_property; g_object_class_install_property (g_object_class, PROP_SRC_CONTAINER, g_param_spec_object ("src-container", @@ -134,15 +82,23 @@ gimp_filtered_container_class_init (GimpFilteredContainerClass *klass) GIMP_TYPE_CONTAINER, GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (g_object_class, PROP_FILTER_FUNC, + g_param_spec_pointer ("filter-func", + NULL, NULL, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (g_object_class, PROP_FILTER_DATA, + g_param_spec_pointer ("filter-data", + NULL, NULL, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void gimp_filtered_container_init (GimpFilteredContainer *filtered_container) { - filtered_container->src_container = NULL; - filtered_container->filter = NULL; - filtered_container->tag_ref_counts = NULL; - filtered_container->tag_count = 0; } static void @@ -153,14 +109,11 @@ gimp_filtered_container_constructed (GObject *object) if (G_OBJECT_CLASS (parent_class)->constructed) G_OBJECT_CLASS (parent_class)->constructed (object); - filtered_container->tag_ref_counts = - g_hash_table_new ((GHashFunc) gimp_tag_get_hash, - (GEqualFunc) gimp_tag_equals); + g_assert (GIMP_IS_CONTAINER (filtered_container->src_container)); + g_assert (filtered_container->filter_func != NULL); - gimp_container_foreach (filtered_container->src_container, - (GFunc) gimp_filtered_container_tagged_item_added, - filtered_container); - gimp_filtered_container_filter (filtered_container); + if (! gimp_container_frozen (filtered_container->src_container)) + gimp_filtered_container_filter (filtered_container); } static void @@ -168,12 +121,6 @@ gimp_filtered_container_dispose (GObject *object) { GimpFilteredContainer *filtered_container = GIMP_FILTERED_CONTAINER (object); - if (filtered_container->tag_ref_counts) - { - g_hash_table_unref (filtered_container->tag_ref_counts); - filtered_container->tag_ref_counts = NULL; - } - if (filtered_container->src_container) { g_signal_handlers_disconnect_by_func (filtered_container->src_container, @@ -223,6 +170,14 @@ gimp_filtered_container_set_property (GObject *object, filtered_container); break; + case PROP_FILTER_FUNC: + filtered_container->filter_func = g_value_get_pointer (value); + break; + + case PROP_FILTER_DATA: + filtered_container->filter_data = g_value_get_pointer (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -243,24 +198,20 @@ gimp_filtered_container_get_property (GObject *object, g_value_set_object (value, filtered_container->src_container); break; + case PROP_FILTER_FUNC: + g_value_set_pointer (value, filtered_container->filter_func); + break; + + case PROP_FILTER_DATA: + g_value_set_pointer (value, filtered_container->filter_data); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } -static gint64 -gimp_filtered_container_get_memsize (GimpObject *object, - gint64 *gui_size) -{ - gint64 memsize = 0; - - /* FIXME take members into account */ - - return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, - gui_size); -} - /** * gimp_filtered_container_new: * @src_container: container to be filtered. @@ -273,164 +224,47 @@ gimp_filtered_container_get_memsize (GimpObject *object, * Return value: a new #GimpFilteredContainer object. **/ GimpContainer * -gimp_filtered_container_new (GimpContainer *src_container, - GCompareFunc sort_func) +gimp_filtered_container_new (GimpContainer *src_container, + GimpObjectFilterFunc filter_func, + gpointer filter_data) { - GimpFilteredContainer *filtered_container; - GType children_type; + GType children_type; + GCompareFunc sort_func; - g_return_val_if_fail (GIMP_IS_CONTAINER (src_container), NULL); + g_return_val_if_fail (GIMP_IS_LIST (src_container), NULL); + g_return_val_if_fail (filter_func != NULL, NULL); children_type = gimp_container_get_children_type (src_container); + sort_func = GIMP_LIST (src_container)->sort_func; - filtered_container = g_object_new (GIMP_TYPE_FILTERED_CONTAINER, - "sort-func", sort_func, - "children-type", children_type, - "policy", GIMP_CONTAINER_POLICY_WEAK, - "unique-names", FALSE, - "src-container", src_container, - NULL); - - return GIMP_CONTAINER (filtered_container); -} - -/** - * gimp_filtered_container_set_filter: - * @filtered_container: a #GimpFilteredContainer object. - * @tags: list of #GimpTag objects. - * - * Sets list of tags to be used for filtering. Only objects which have all of - * the tags assigned match filtering criteria. - **/ -void -gimp_filtered_container_set_filter (GimpFilteredContainer *filtered_container, - GList *tags) -{ - g_return_if_fail (GIMP_IS_FILTERED_CONTAINER (filtered_container)); - - filtered_container->filter = tags; - - gimp_container_freeze (GIMP_CONTAINER (filtered_container)); - gimp_filtered_container_filter (filtered_container); - gimp_container_thaw (GIMP_CONTAINER (filtered_container)); -} - -/** - * gimp_filtered_container_get_filter: - * @filtered_container: a #GimpFilteredContainer object. - * - * Returns current tag filter. Tag filter is a list of GimpTag objects, which - * must be contained by each object matching filter criteria. - * - * Return value: a list of GimpTag objects used as filter. This value should - * not be modified or freed. - **/ -const GList * -gimp_filtered_container_get_filter (GimpFilteredContainer *filtered_container) -{ - g_return_val_if_fail (GIMP_IS_FILTERED_CONTAINER (filtered_container), NULL); - - return filtered_container->filter; -} - -static gboolean -gimp_filtered_container_object_matches (GimpFilteredContainer *filtered_container, - GimpObject *object) -{ - GList *filter_tag; - GList *object_tag; - - filter_tag = filtered_container->filter; - while (filter_tag) - { - if (! filter_tag->data) - { - /* invalid tag - does not match */ - return FALSE; - } - - object_tag = gimp_tagged_get_tags (GIMP_TAGGED (object)); - while (object_tag) - { - if (gimp_tag_equals (GIMP_TAG (object_tag->data), - GIMP_TAG (filter_tag->data))) - { - /* found match for the tag */ - break; - } - object_tag = g_list_next (object_tag); - } - - if (! object_tag) - { - /* match for the tag was not found. - * since query is of type AND, it whole fails. */ - return FALSE; - } - - filter_tag = g_list_next (filter_tag); - } - - return TRUE; -} - -static void -gimp_filtered_container_check_needs_remove (GimpObject *object, - MatchParams *match_params) -{ - if (! gimp_filtered_container_object_matches (match_params->filtered_container, - object)) - { - match_params->items_to_remove = g_list_prepend (match_params->items_to_remove, - object); - } -} - -static void -gimp_filtered_container_check_needs_add (GimpObject *object, - MatchParams *match_params) -{ - if (gimp_filtered_container_object_matches (match_params->filtered_container, - object) && - ! gimp_container_have (GIMP_CONTAINER (match_params->filtered_container), - object)) - { - match_params->items_to_add = g_list_prepend (match_params->items_to_add, - object); - } + return g_object_new (GIMP_TYPE_FILTERED_CONTAINER, + "sort-func", sort_func, + "children-type", children_type, + "policy", GIMP_CONTAINER_POLICY_WEAK, + "unique-names", FALSE, + "src-container", src_container, + "filter-func", filter_func, + "filter-data", filter_data, + NULL); } static void gimp_filtered_container_filter (GimpFilteredContainer *filtered_container) { - MatchParams match_params; - GList *list; + GList *list; - match_params.filtered_container = filtered_container; - match_params.items_to_add = NULL; - match_params.items_to_remove = NULL; - - gimp_container_foreach (GIMP_CONTAINER (filtered_container), - (GFunc) gimp_filtered_container_check_needs_remove, - &match_params); - gimp_container_foreach (GIMP_CONTAINER (filtered_container->src_container), - (GFunc) gimp_filtered_container_check_needs_add, - &match_params); - - for (list = match_params.items_to_remove; list; list = g_list_next (list)) + for (list = GIMP_LIST (filtered_container->src_container)->list; + list; + list = g_list_next (list)) { - gimp_container_remove (GIMP_CONTAINER (filtered_container), - GIMP_OBJECT (list->data)); - } + GimpObject *child = list->data; - for (list = match_params.items_to_add; list; list = g_list_next (list)) - { - gimp_container_add (GIMP_CONTAINER (filtered_container), - GIMP_OBJECT (list->data)); + if (filtered_container->filter_func (child, + filtered_container->filter_data)) + { + gimp_container_add (GIMP_CONTAINER (filtered_container), child); + } } - - g_list_free (match_params.items_to_add); - g_list_free (match_params.items_to_remove); } static void @@ -438,10 +272,8 @@ gimp_filtered_container_src_add (GimpContainer *src_container, GimpObject *obj, GimpFilteredContainer *filtered_container) { - gimp_filtered_container_tagged_item_added (GIMP_TAGGED (obj), - filtered_container); - - if (! gimp_container_frozen (src_container)) + if (! gimp_container_frozen (src_container) && + filtered_container->filter_func (obj, filtered_container->filter_data)) { gimp_container_add (GIMP_CONTAINER (filtered_container), obj); } @@ -452,11 +284,8 @@ gimp_filtered_container_src_remove (GimpContainer *src_container, GimpObject *obj, GimpFilteredContainer *filtered_container) { - gimp_filtered_container_tagged_item_removed (GIMP_TAGGED (obj), - filtered_container); - if (! gimp_container_frozen (src_container) && - gimp_container_have (GIMP_CONTAINER (filtered_container), obj)) + filtered_container->filter_func (obj, filtered_container->filter_data)) { gimp_container_remove (GIMP_CONTAINER (filtered_container), obj); } @@ -477,122 +306,3 @@ gimp_filtered_container_src_thaw (GimpContainer *src_container, gimp_filtered_container_filter (filtered_container); gimp_container_thaw (GIMP_CONTAINER (filtered_container)); } - -static void -gimp_filtered_container_tagged_item_added (GimpTagged *tagged, - GimpFilteredContainer *filtered_container) -{ - GList *list; - - for (list = gimp_tagged_get_tags (tagged); list; list = g_list_next (list)) - { - gimp_filtered_container_tag_added (tagged, - list->data, - filtered_container); - } - - g_signal_connect (tagged, "tag-added", - G_CALLBACK (gimp_filtered_container_tag_added), - filtered_container); - g_signal_connect (tagged, "tag-removed", - G_CALLBACK (gimp_filtered_container_tag_removed), - filtered_container); -} - -static void -gimp_filtered_container_tagged_item_removed (GimpTagged *tagged, - GimpFilteredContainer *filtered_container) -{ - GList *list; - - g_signal_handlers_disconnect_by_func (tagged, - gimp_filtered_container_tag_added, - filtered_container); - g_signal_handlers_disconnect_by_func (tagged, - gimp_filtered_container_tag_removed, - filtered_container); - - for (list = gimp_tagged_get_tags (tagged); list; list = g_list_next (list)) - { - gimp_filtered_container_tag_removed (tagged, - GIMP_TAG (list->data), - filtered_container); - } - -} - -static void -gimp_filtered_container_tag_added (GimpTagged *tagged, - GimpTag *tag, - GimpFilteredContainer *filtered_container) -{ - gint ref_count; - - ref_count = GPOINTER_TO_INT (g_hash_table_lookup (filtered_container->tag_ref_counts, - tag)); - ref_count++; - g_hash_table_insert (filtered_container->tag_ref_counts, - tag, GINT_TO_POINTER (ref_count)); - if (ref_count == 1) - { - filtered_container->tag_count++; - g_signal_emit (filtered_container, - gimp_filtered_container_signals[TAG_COUNT_CHANGED], 0, - filtered_container->tag_count); - } -} - -static void -gimp_filtered_container_tag_removed (GimpTagged *tagged, - GimpTag *tag, - GimpFilteredContainer *filtered_container) -{ - gint ref_count; - - ref_count = GPOINTER_TO_INT (g_hash_table_lookup (filtered_container->tag_ref_counts, - tag)); - ref_count--; - - if (ref_count > 0) - { - g_hash_table_insert (filtered_container->tag_ref_counts, - tag, GINT_TO_POINTER (ref_count)); - } - else - { - if (g_hash_table_remove (filtered_container->tag_ref_counts, tag)) - { - filtered_container->tag_count--; - g_signal_emit (filtered_container, - gimp_filtered_container_signals[TAG_COUNT_CHANGED], 0, - filtered_container->tag_count); - } - } -} - -static void -gimp_filtered_container_tag_count_changed (GimpFilteredContainer *container, - gint tag_count) -{ -} - -/** - * gimp_filtered_container_get_tag_count: - * @container: a #GimpFilteredContainer object. - * - * Get number of distinct tags that are currently assigned to all - * objects in the container. The count is independent of currently - * used filter, it is provided for all available objects (ie. empty - * filter). - * - * Return value: number of distinct tags assigned to all objects in the - * container. - **/ -gint -gimp_filtered_container_get_tag_count (GimpFilteredContainer *container) -{ - g_return_val_if_fail (GIMP_IS_FILTERED_CONTAINER (container), 0); - - return container->tag_count; -} -#endif diff --git a/app/core/gimpfilteredcontainer.h b/app/core/gimpfilteredcontainer.h index d45013e309..3264ab194e 100644 --- a/app/core/gimpfilteredcontainer.h +++ b/app/core/gimpfilteredcontainer.h @@ -1,9 +1,9 @@ -#if 0 /* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis * * gimpfilteredcontainer.h * Copyright (C) 2008 Aurimas Juška + * 2011 Michael Natterer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,34 +38,24 @@ typedef struct _GimpFilteredContainerClass GimpFilteredContainerClass; struct _GimpFilteredContainer { - GimpList parent_instance; + GimpList parent_instance; - GimpContainer *src_container; - GList *filter; - GHashTable *tag_ref_counts; - gint tag_count; + GimpContainer *src_container; + GimpObjectFilterFunc filter_func; + gpointer filter_data; }; struct _GimpFilteredContainerClass { GimpContainerClass parent_class; - - void (* tag_count_changed) (GimpFilteredContainer *container, - gint count); }; -GType gimp_filtered_container_get_type (void) G_GNUC_CONST; +GType gimp_filtered_container_get_type (void) G_GNUC_CONST; -GimpContainer * gimp_filtered_container_new (GimpContainer *src_container, - GCompareFunc sort_func); - -void gimp_filtered_container_set_filter (GimpFilteredContainer *filtered_container, - GList *tags); -const GList * gimp_filtered_container_get_filter (GimpFilteredContainer *filtered_container); - -gint gimp_filtered_container_get_tag_count (GimpFilteredContainer *container); +GimpContainer * gimp_filtered_container_new (GimpContainer *src_container, + GimpObjectFilterFunc filter_func, + gpointer filter_data); #endif /* __GIMP_FILTERED_CONTAINER_H__ */ -#endif