app: Port GimpParasiteList to GListModel

GListModels are fun. They will also prove to be useful in the future.
This commit is contained in:
Niels De Graef 2023-05-21 01:28:04 +02:00
parent 997e4b5f6c
commit 3054901af0
6 changed files with 162 additions and 281 deletions

View File

@ -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, &current);
return list;
return gimp_parasite_list_list_names (gimp->parasites);
}

View File

@ -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

View File

@ -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

View File

@ -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, &parasite_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, &parasite_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;
}

View File

@ -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__ */

View File

@ -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 (&parasite);
}
if (err != NULL)
{
g_propagate_error (error, err);
return FALSE;
}