From 3054901af0cb90b69945350aaee33bdd53c470ce Mon Sep 17 00:00:00 2001 From: Niels De Graef Date: Sun, 21 May 2023 01:28:04 +0200 Subject: [PATCH] app: Port GimpParasiteList to GListModel GListModels are fun. They will also prove to be useful in the future. --- app/core/gimp-parasites.c | 20 +-- app/core/gimpimage.c | 19 +-- app/core/gimpitem.c | 22 +-- app/core/gimpparasitelist.c | 294 ++++++++++++++++-------------------- app/core/gimpparasitelist.h | 43 +----- app/xcf/xcf-save.c | 45 +++--- 6 files changed, 162 insertions(+), 281 deletions(-) diff --git a/app/core/gimp-parasites.c b/app/core/gimp-parasites.c index b6d06f6df1..fb75d3056e 100644 --- a/app/core/gimp-parasites.c +++ b/app/core/gimp-parasites.c @@ -70,30 +70,12 @@ 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); - 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; + return gimp_parasite_list_list_names (gimp->parasites); } diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 4891734003..2d0123f461 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -4235,32 +4235,15 @@ 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); - - 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; + return gimp_parasite_list_list_names (private->parasites); } gboolean diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c index 5efeac3d16..a0baba225b 100644 --- a/app/core/gimpitem.c +++ b/app/core/gimpitem.c @@ -2286,35 +2286,15 @@ 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); - - 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; + return gimp_parasite_list_list_names (private->parasites); } gboolean diff --git a/app/core/gimpparasitelist.c b/app/core/gimpparasitelist.c index 242c3fa3a9..02ff949382 100644 --- a/app/core/gimpparasitelist.c +++ b/app/core/gimpparasitelist.c @@ -30,11 +30,11 @@ #include "gimpparasitelist.h" -enum +struct _GimpParasiteList { - ADD, - REMOVE, - LAST_SIGNAL + GimpObject parent_instance; + + GPtrArray *parasites; }; @@ -42,6 +42,7 @@ 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, @@ -52,27 +53,15 @@ 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"; @@ -82,30 +71,9 @@ 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 @@ -121,7 +89,7 @@ gimp_parasite_list_config_iface_init (gpointer iface, static void gimp_parasite_list_init (GimpParasiteList *list) { - list->table = NULL; + list->parasites = g_ptr_array_new_full (1, (GDestroyNotify) gimp_parasite_free); } static void @@ -129,16 +97,43 @@ gimp_parasite_list_finalize (GObject *object) { GimpParasiteList *list = GIMP_PARASITE_LIST (object); - if (list->table) - { - g_hash_table_foreach_remove (list->table, (GHRFunc) parasite_free, NULL); - g_hash_table_destroy (list->table); - list->table = NULL; - } + g_clear_pointer (&list->parasites, g_ptr_array_unref); 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) @@ -146,24 +141,47 @@ gimp_parasite_list_get_memsize (GimpObject *object, GimpParasiteList *list = GIMP_PARASITE_LIST (object); gint64 memsize = 0; - memsize += gimp_g_hash_table_get_memsize_foreach (list->table, - (GimpMemsizeFunc) - gimp_parasite_get_memsize, - gui_size); + 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); + } return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object, gui_size); } static gboolean -gimp_parasite_list_serialize (GimpConfig *list, +gimp_parasite_list_serialize (GimpConfig *config, GimpConfigWriter *writer, gpointer data) { - if (GIMP_PARASITE_LIST (list)->table) - g_hash_table_foreach (GIMP_PARASITE_LIST (list)->table, - (GHFunc) parasite_serialize, - writer); + 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); + } return TRUE; } @@ -297,8 +315,12 @@ gimp_parasite_list_copy (GimpParasiteList *list) newlist = gimp_parasite_list_new (); - if (list->table) - g_hash_table_foreach (list->table, (GHFunc) parasite_copy, newlist); + for (guint i = 0; i < list->parasites->len; i++) + { + GimpParasite *parasite = g_ptr_array_index (list->parasites, i); + + gimp_parasite_list_add (newlist, parasite); + } return newlist; } @@ -307,146 +329,96 @@ 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); - copy = gimp_parasite_copy (parasite); - g_hash_table_insert (list->table, copy->name, copy); - - g_signal_emit (list, parasite_list_signals[ADD], 0, copy); + 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); } void gimp_parasite_list_remove (GimpParasiteList *list, const gchar *name) { + const GimpParasite *parasite; + guint idx; + g_return_if_fail (GIMP_IS_PARASITE_LIST (list)); - if (list->table) + parasite = gimp_parasite_list_find_full (list, name, &idx); + + if (parasite) { - 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); - } + g_ptr_array_remove_index (list->parasites, idx); + g_list_model_items_changed (G_LIST_MODEL (list), idx, 1, 0); } } -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 +guint gimp_parasite_list_persistent_length (GimpParasiteList *list) { - gint len = 0; + guint count = 0; g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), 0); - if (! list->table) - return 0; + for (guint i = 0; i < list->parasites->len; i++) + { + GimpParasite *parasite = g_ptr_array_index (list->parasites, i); - gimp_parasite_list_foreach (list, - (GHFunc) parasite_count_if_persistent, &len); + if (gimp_parasite_is_persistent (parasite)) + count++; + } - return len; + return count; } -void -gimp_parasite_list_foreach (GimpParasiteList *list, - GHFunc function, - gpointer user_data) +const GimpParasite * +gimp_parasite_list_find_full (GimpParasiteList *list, + const gchar *name, + guint *index) { - g_return_if_fail (GIMP_IS_PARASITE_LIST (list)); + g_return_val_if_fail (GIMP_IS_PARASITE_LIST (list), NULL); + g_return_val_if_fail (name != NULL, NULL); - if (! list->table) - return; + for (guint i = 0; i < list->parasites->len; i++) + { + GimpParasite *parasite = g_ptr_array_index (list->parasites, i); - g_hash_table_foreach (list->table, function, user_data); + if (g_strcmp0 (parasite->name, name) == 0) + { + if (index != NULL) + *index = i; + return parasite; + } + } + + return NULL; } 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); - if (list->table) - return (GimpParasite *) g_hash_table_lookup (list->table, name); + names = g_new0 (gchar *, list->parasites->len + 1); - 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; + 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; } diff --git a/app/core/gimpparasitelist.h b/app/core/gimpparasitelist.h index 17627531c0..3711a26850 100644 --- a/app/core/gimpparasitelist.h +++ b/app/core/gimpparasitelist.h @@ -21,35 +21,9 @@ #include "gimpobject.h" -#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; +#define GIMP_TYPE_PARASITE_LIST (gimp_parasite_list_get_type ()) +G_DECLARE_FINAL_TYPE (GimpParasiteList, gimp_parasite_list, + GIMP, PARASITE_LIST, GimpObject) GimpParasiteList * gimp_parasite_list_new (void); GimpParasiteList * gimp_parasite_list_copy (GimpParasiteList *list); @@ -57,13 +31,12 @@ void gimp_parasite_list_add (GimpParasiteList *list, const GimpParasite *parasite); void gimp_parasite_list_remove (GimpParasiteList *list, const gchar *name); -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); +guint gimp_parasite_list_persistent_length (GimpParasiteList *list); 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 4d3fa7bd86..851b4b43cc 100644 --- a/app/xcf/xcf-save.c +++ b/app/xcf/xcf-save.c @@ -565,7 +565,7 @@ xcf_save_image_props (XcfInfo *info, } } - if (gimp_parasite_list_length (private->parasites) > 0) + if (g_list_model_get_n_items (G_LIST_MODEL (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 (gimp_parasite_list_length (parasites) > 0) + if (g_list_model_get_n_items (G_LIST_MODEL (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 (gimp_parasite_list_length (parasites) > 0) + if (g_list_model_get_n_items (G_LIST_MODEL (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 (gimp_parasite_list_length (parasites) > 0) + if (g_list_model_get_n_items (G_LIST_MODEL (parasites)) > 0) { xcf_check_error (xcf_save_prop (info, image, PROP_PARASITES, error, parasites), ;); @@ -2438,36 +2438,27 @@ 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) { - XcfParasiteData data; + GError *err = NULL; - data.info = info; - data.error = NULL; - - gimp_parasite_list_foreach (list, (GHFunc) xcf_save_parasite_func, &data); - - if (data.error) + for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (list)); i++) { - g_propagate_error (error, 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); return FALSE; }