diff --git a/app/core/gimp-parasites.c b/app/core/gimp-parasites.c index fb75d3056e..b6d06f6df1 100644 --- a/app/core/gimp-parasites.c +++ b/app/core/gimp-parasites.c @@ -70,12 +70,30 @@ gimp_parasite_find (Gimp *gimp, return gimp_parasite_list_find (gimp->parasites, name); } +static void +list_func (const gchar *key, + GimpParasite *parasite, + gchar ***current) +{ + *(*current)++ = g_strdup (key); +} + gchar ** gimp_parasite_list (Gimp *gimp) { + gint count; + gchar **list; + gchar **current; + g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); - return gimp_parasite_list_list_names (gimp->parasites); + count = gimp_parasite_list_length (gimp->parasites); + + list = current = g_new0 (gchar *, count + 1); + + gimp_parasite_list_foreach (gimp->parasites, (GHFunc) list_func, ¤t); + + return list; } diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 2d0123f461..4891734003 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -4235,15 +4235,32 @@ gimp_image_parasite_find (GimpImage *image, name); } +static void +list_func (gchar *key, + GimpParasite *p, + gchar ***cur) +{ + *(*cur)++ = (gchar *) g_strdup (key); +} + gchar ** gimp_image_parasite_list (GimpImage *image) { GimpImagePrivate *private; + gint count; + gchar **list; + gchar **cur; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); private = GIMP_IMAGE_GET_PRIVATE (image); - return gimp_parasite_list_list_names (private->parasites); + + count = gimp_parasite_list_length (private->parasites); + cur = list = g_new0 (gchar *, count + 1); + + gimp_parasite_list_foreach (private->parasites, (GHFunc) list_func, &cur); + + return list; } gboolean diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c index a0baba225b..5efeac3d16 100644 --- a/app/core/gimpitem.c +++ b/app/core/gimpitem.c @@ -2286,15 +2286,35 @@ gimp_item_parasite_find (GimpItem *item, return gimp_parasite_list_find (GET_PRIVATE (item)->parasites, name); } +static void +gimp_item_parasite_list_foreach_func (gchar *name, + GimpParasite *parasite, + gchar ***cur) +{ + *(*cur)++ = (gchar *) g_strdup (name); +} + gchar ** gimp_item_parasite_list (GimpItem *item) { GimpItemPrivate *private; + gint count; + gchar **list; + gchar **cur; g_return_val_if_fail (GIMP_IS_ITEM (item), NULL); private = GET_PRIVATE (item); - return gimp_parasite_list_list_names (private->parasites); + + count = gimp_parasite_list_length (private->parasites); + + cur = list = g_new0 (gchar *, count + 1); + + gimp_parasite_list_foreach (private->parasites, + (GHFunc) gimp_item_parasite_list_foreach_func, + &cur); + + return list; } gboolean diff --git a/app/core/gimpparasitelist.c b/app/core/gimpparasitelist.c index 02ff949382..242c3fa3a9 100644 --- a/app/core/gimpparasitelist.c +++ b/app/core/gimpparasitelist.c @@ -30,11 +30,11 @@ #include "gimpparasitelist.h" -struct _GimpParasiteList +enum { - GimpObject parent_instance; - - GPtrArray *parasites; + ADD, + REMOVE, + LAST_SIGNAL }; @@ -42,7 +42,6 @@ static void gimp_parasite_list_finalize (GObject *object); static gint64 gimp_parasite_list_get_memsize (GimpObject *object, gint64 *gui_size); -static void gimp_parasite_list_model_iface_init (GListModelInterface *iface); static void gimp_parasite_list_config_iface_init (gpointer iface, gpointer iface_data); static gboolean gimp_parasite_list_serialize (GimpConfig *list, @@ -53,15 +52,27 @@ static gboolean gimp_parasite_list_deserialize (GimpConfig *list, gint nest_level, gpointer data); +static void parasite_serialize (const gchar *key, + GimpParasite *parasite, + GimpConfigWriter *writer); +static void parasite_copy (const gchar *key, + GimpParasite *parasite, + GimpParasiteList *list); +static gboolean parasite_free (const gchar *key, + GimpParasite *parasite, + gpointer unused); +static void parasite_count_if_persistent (const gchar *key, + GimpParasite *parasite, + gint *count); + G_DEFINE_TYPE_WITH_CODE (GimpParasiteList, gimp_parasite_list, GIMP_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, - gimp_parasite_list_model_iface_init) G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG, gimp_parasite_list_config_iface_init)) #define parent_class gimp_parasite_list_parent_class +static guint parasite_list_signals[LAST_SIGNAL] = { 0 }; static const gchar parasite_symbol[] = "parasite"; @@ -71,9 +82,30 @@ gimp_parasite_list_class_init (GimpParasiteListClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); + parasite_list_signals[ADD] = + g_signal_new ("add", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpParasiteListClass, add), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + + parasite_list_signals[REMOVE] = + g_signal_new ("remove", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpParasiteListClass, remove), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_POINTER); + object_class->finalize = gimp_parasite_list_finalize; gimp_object_class->get_memsize = gimp_parasite_list_get_memsize; + + klass->add = NULL; + klass->remove = NULL; } static void @@ -89,7 +121,7 @@ gimp_parasite_list_config_iface_init (gpointer iface, static void gimp_parasite_list_init (GimpParasiteList *list) { - list->parasites = g_ptr_array_new_full (1, (GDestroyNotify) gimp_parasite_free); + list->table = NULL; } static void @@ -97,43 +129,16 @@ gimp_parasite_list_finalize (GObject *object) { GimpParasiteList *list = GIMP_PARASITE_LIST (object); - g_clear_pointer (&list->parasites, g_ptr_array_unref); + if (list->table) + { + g_hash_table_foreach_remove (list->table, (GHRFunc) parasite_free, NULL); + g_hash_table_destroy (list->table); + list->table = NULL; + } G_OBJECT_CLASS (parent_class)->finalize (object); } -static GType -gimp_parasite_list_get_item_type (GListModel *list) -{ - return GIMP_TYPE_PARASITE; -} - -static guint -gimp_parasite_list_get_n_items (GListModel *list) -{ - GimpParasiteList *self = GIMP_PARASITE_LIST (list); - return self->parasites->len; -} - -static gpointer -gimp_parasite_list_get_item (GListModel *list, - guint index) -{ - GimpParasiteList *self = GIMP_PARASITE_LIST (list); - - if (index >= self->parasites->len) - return NULL; - return g_object_ref (g_ptr_array_index (self->parasites, index)); -} - -static void -gimp_parasite_list_model_iface_init (GListModelInterface *iface) -{ - iface->get_item_type = gimp_parasite_list_get_item_type; - iface->get_n_items = gimp_parasite_list_get_n_items; - iface->get_item = gimp_parasite_list_get_item; -} - static gint64 gimp_parasite_list_get_memsize (GimpObject *object, gint64 *gui_size) @@ -141,47 +146,24 @@ gimp_parasite_list_get_memsize (GimpObject *object, GimpParasiteList *list = GIMP_PARASITE_LIST (object); gint64 memsize = 0; - for (guint i = 0; i < list->parasites->len; i++) - { - GimpParasite *parasite = g_ptr_array_index (list->parasites, i); - - memsize += gimp_parasite_get_memsize (parasite, gui_size); - } + memsize += gimp_g_hash_table_get_memsize_foreach (list->table, + (GimpMemsizeFunc) + gimp_parasite_get_memsize, + gui_size); return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); } static gboolean -gimp_parasite_list_serialize (GimpConfig *config, +gimp_parasite_list_serialize (GimpConfig *list, GimpConfigWriter *writer, gpointer data) { - GimpParasiteList *list = GIMP_PARASITE_LIST (config); - guint i; - - for (i = 0; i < list->parasites->len; i++) - { - GimpParasite *parasite = g_ptr_array_index (list->parasites, i); - const guint8 *parasite_contents; - guint32 parasite_size; - - if (! gimp_parasite_is_persistent (parasite)) - continue; - - gimp_config_writer_open (writer, parasite_symbol); - - parasite_contents = gimp_parasite_get_data (parasite, ¶site_size); - gimp_config_writer_printf (writer, "\"%s\" %lu %lu", - gimp_parasite_get_name (parasite), - gimp_parasite_get_flags (parasite), - (long unsigned int) parasite_size); - - gimp_config_writer_data (writer, parasite_size, parasite_contents); - - gimp_config_writer_close (writer); - gimp_config_writer_linefeed (writer); - } + if (GIMP_PARASITE_LIST (list)->table) + g_hash_table_foreach (GIMP_PARASITE_LIST (list)->table, + (GHFunc) parasite_serialize, + writer); return TRUE; } @@ -315,12 +297,8 @@ gimp_parasite_list_copy (GimpParasiteList *list) newlist = gimp_parasite_list_new (); - for (guint i = 0; i < list->parasites->len; i++) - { - GimpParasite *parasite = g_ptr_array_index (list->parasites, i); - - gimp_parasite_list_add (newlist, parasite); - } + if (list->table) + g_hash_table_foreach (list->table, (GHFunc) parasite_copy, newlist); return newlist; } @@ -329,96 +307,146 @@ void gimp_parasite_list_add (GimpParasiteList *list, const GimpParasite *parasite) { + GimpParasite *copy; + g_return_if_fail (GIMP_IS_PARASITE_LIST (list)); g_return_if_fail (parasite != NULL); g_return_if_fail (parasite->name != NULL); + if (list->table == NULL) + list->table = g_hash_table_new (g_str_hash, g_str_equal); + gimp_parasite_list_remove (list, parasite->name); - g_ptr_array_add (list->parasites, gimp_parasite_copy (parasite)); - g_list_model_items_changed (G_LIST_MODEL (list), - list->parasites->len - 1, 0, 1); + copy = gimp_parasite_copy (parasite); + g_hash_table_insert (list->table, copy->name, copy); + + g_signal_emit (list, parasite_list_signals[ADD], 0, copy); } void gimp_parasite_list_remove (GimpParasiteList *list, const gchar *name) { - const GimpParasite *parasite; - guint idx; - g_return_if_fail (GIMP_IS_PARASITE_LIST (list)); - parasite = gimp_parasite_list_find_full (list, name, &idx); - - if (parasite) + if (list->table) { - g_ptr_array_remove_index (list->parasites, idx); - g_list_model_items_changed (G_LIST_MODEL (list), idx, 1, 0); + GimpParasite *parasite; + + parasite = (GimpParasite *) gimp_parasite_list_find (list, name); + + if (parasite) + { + g_hash_table_remove (list->table, name); + + g_signal_emit (list, parasite_list_signals[REMOVE], 0, parasite); + + gimp_parasite_free (parasite); + } } } -guint +gint +gimp_parasite_list_length (GimpParasiteList *list) +{ + g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), 0); + + if (! list->table) + return 0; + + return g_hash_table_size (list->table); +} + +gint gimp_parasite_list_persistent_length (GimpParasiteList *list) { - guint count = 0; + gint len = 0; g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), 0); - for (guint i = 0; i < list->parasites->len; i++) - { - GimpParasite *parasite = g_ptr_array_index (list->parasites, i); + if (! list->table) + return 0; - if (gimp_parasite_is_persistent (parasite)) - count++; - } + gimp_parasite_list_foreach (list, + (GHFunc) parasite_count_if_persistent, &len); - return count; + return len; } -const GimpParasite * -gimp_parasite_list_find_full (GimpParasiteList *list, - const gchar *name, - guint *index) +void +gimp_parasite_list_foreach (GimpParasiteList *list, + GHFunc function, + gpointer user_data) { - g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), NULL); - g_return_val_if_fail (name != NULL, NULL); + g_return_if_fail (GIMP_IS_PARASITE_LIST (list)); - for (guint i = 0; i < list->parasites->len; i++) - { - GimpParasite *parasite = g_ptr_array_index (list->parasites, i); + if (! list->table) + return; - if (g_strcmp0 (parasite->name, name) == 0) - { - if (index != NULL) - *index = i; - return parasite; - } - } - - return NULL; + g_hash_table_foreach (list->table, function, user_data); } const GimpParasite * gimp_parasite_list_find (GimpParasiteList *list, const gchar *name) { - return gimp_parasite_list_find_full (list, name, NULL); -} - -gchar ** -gimp_parasite_list_list_names (GimpParasiteList *list) -{ - gchar **names; - g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), NULL); - names = g_new0 (gchar *, list->parasites->len + 1); + if (list->table) + return (GimpParasite *) g_hash_table_lookup (list->table, name); - for (guint i = 0; i < list->parasites->len; i++) - { - GimpParasite *parasite = g_ptr_array_index (list->parasites, i); - names[i] = g_strdup (parasite->name); - } - - return names; + return NULL; +} + + +static void +parasite_serialize (const gchar *key, + GimpParasite *parasite, + GimpConfigWriter *writer) +{ + const guint8 *parasite_contents; + guint32 parasite_size; + + if (! gimp_parasite_is_persistent (parasite)) + return; + + gimp_config_writer_open (writer, parasite_symbol); + + parasite_contents = gimp_parasite_get_data (parasite, ¶site_size); + gimp_config_writer_printf (writer, "\"%s\" %lu %lu", + gimp_parasite_get_name (parasite), + gimp_parasite_get_flags (parasite), + (long unsigned int) parasite_size); + + gimp_config_writer_data (writer, parasite_size, parasite_contents); + + gimp_config_writer_close (writer); + gimp_config_writer_linefeed (writer); +} + +static void +parasite_copy (const gchar *key, + GimpParasite *parasite, + GimpParasiteList *list) +{ + gimp_parasite_list_add (list, parasite); +} + +static gboolean +parasite_free (const gchar *key, + GimpParasite *parasite, + gpointer unused) +{ + gimp_parasite_free (parasite); + + return TRUE; +} + +static void +parasite_count_if_persistent (const gchar *key, + GimpParasite *parasite, + gint *count) +{ + if (gimp_parasite_is_persistent (parasite)) + *count = *count + 1; } diff --git a/app/core/gimpparasitelist.h b/app/core/gimpparasitelist.h index 3711a26850..17627531c0 100644 --- a/app/core/gimpparasitelist.h +++ b/app/core/gimpparasitelist.h @@ -21,9 +21,35 @@ #include "gimpobject.h" -#define GIMP_TYPE_PARASITE_LIST (gimp_parasite_list_get_type ()) -G_DECLARE_FINAL_TYPE (GimpParasiteList, gimp_parasite_list, - GIMP, PARASITE_LIST, GimpObject) +#define GIMP_TYPE_PARASITE_LIST (gimp_parasite_list_get_type ()) +#define GIMP_PARASITE_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_PARASITE_LIST, GimpParasiteList)) +#define GIMP_PARASITE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_PARASITE_LIST, GimpParasiteListClass)) +#define GIMP_IS_PARASITE_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_PARASITE_LIST)) +#define GIMP_IS_PARASITE_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_PARASITE_LIST)) +#define GIMP_PARASITE_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_PARASITE_LIST, GimpParasiteListClass)) + + +typedef struct _GimpParasiteListClass GimpParasiteListClass; + +struct _GimpParasiteList +{ + GimpObject object; + + GHashTable *table; +}; + +struct _GimpParasiteListClass +{ + GimpObjectClass parent_class; + + void (* add) (GimpParasiteList *list, + GimpParasite *parasite); + void (* remove) (GimpParasiteList *list, + GimpParasite *parasite); +}; + + +GType gimp_parasite_list_get_type (void) G_GNUC_CONST; GimpParasiteList * gimp_parasite_list_new (void); GimpParasiteList * gimp_parasite_list_copy (GimpParasiteList *list); @@ -31,12 +57,13 @@ void gimp_parasite_list_add (GimpParasiteList *list, const GimpParasite *parasite); void gimp_parasite_list_remove (GimpParasiteList *list, const gchar *name); -guint gimp_parasite_list_persistent_length (GimpParasiteList *list); +gint gimp_parasite_list_length (GimpParasiteList *list); +gint gimp_parasite_list_persistent_length (GimpParasiteList *list); +void gimp_parasite_list_foreach (GimpParasiteList *list, + GHFunc function, + gpointer user_data); const GimpParasite * gimp_parasite_list_find (GimpParasiteList *list, const gchar *name); -const GimpParasite * gimp_parasite_list_find_full (GimpParasiteList *list, - const gchar *name, - guint *index); -gchar ** gimp_parasite_list_list_names (GimpParasiteList *list); + #endif /* __GIMP_PARASITE_LIST_H__ */ diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c index 851b4b43cc..4d3fa7bd86 100644 --- a/app/xcf/xcf-save.c +++ b/app/xcf/xcf-save.c @@ -565,7 +565,7 @@ xcf_save_image_props (XcfInfo *info, } } - if (g_list_model_get_n_items (G_LIST_MODEL (private->parasites)) > 0) + if (gimp_parasite_list_length (private->parasites) > 0) { xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error, private->parasites), ;); @@ -723,7 +723,7 @@ xcf_save_layer_props (XcfInfo *info, parasites = gimp_item_get_parasites (GIMP_ITEM (layer)); - if (g_list_model_get_n_items (G_LIST_MODEL (parasites)) > 0) + if (gimp_parasite_list_length (parasites) > 0) { xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error, parasites), ;); @@ -790,7 +790,7 @@ xcf_save_channel_props (XcfInfo *info, parasites = gimp_item_get_parasites (GIMP_ITEM (channel)); - if (g_list_model_get_n_items (G_LIST_MODEL (parasites)) > 0) + if (gimp_parasite_list_length (parasites) > 0) { xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error, parasites), ;); @@ -842,7 +842,7 @@ xcf_save_path_props (XcfInfo *info, parasites = gimp_item_get_parasites (GIMP_ITEM (vectors)); - if (g_list_model_get_n_items (G_LIST_MODEL (parasites)) > 0) + if (gimp_parasite_list_length (parasites) > 0) { xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error, parasites), ;); @@ -2438,27 +2438,36 @@ xcf_save_parasite (XcfInfo *info, return TRUE; } +typedef struct +{ + XcfInfo *info; + GError *error; +} XcfParasiteData; + +static void +xcf_save_parasite_func (gchar *key, + GimpParasite *parasite, + XcfParasiteData *data) +{ + if (! data->error) + xcf_save_parasite (data->info, parasite, &data->error); +} + static gboolean xcf_save_parasite_list (XcfInfo *info, GimpParasiteList *list, GError **error) { - GError *err = NULL; + XcfParasiteData data; - for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (list)); i++) + data.info = info; + data.error = NULL; + + gimp_parasite_list_foreach (list, (GHFunc) xcf_save_parasite_func, &data); + + if (data.error) { - GimpParasite *parasite; - - parasite = g_list_model_get_item (G_LIST_MODEL (list), i); - if (err == NULL) - xcf_save_parasite (info, parasite, &err); - - g_clear_object (¶site); - } - - if (err != NULL) - { - g_propagate_error (error, err); + g_propagate_error (error, data.error); return FALSE; }