[gimp/gimp-2-10] app: make GimpDataFactory properly derivable



commit 0c04d3784b3d2819ce47ef8afb11cdcb53e9ed4f
Author: Michael Natterer <mitch gimp org>
Date:   Sat Jun 2 21:50:34 2018 +0200

    app: make GimpDataFactory properly derivable
    
    Virtualize a lot of functions and move their code into the default
    implementation. Also connect to changes of the "path" property and
    reload data automatically when the path changes. Add "wait" method
    which is by default empty but is to be implemented by fonts.
    
    (cherry picked from commit 01e41042363ed26a676c9eed1d82132607138502)

 app/core/gimpdatafactory.c | 755 ++++++++++++++++++++++++++++++---------------
 app/core/gimpdatafactory.h |  34 +-
 2 files changed, 540 insertions(+), 249 deletions(-)
---
diff --git a/app/core/gimpdatafactory.c b/app/core/gimpdatafactory.c
index f1becc65ac..0a073de932 100644
--- a/app/core/gimpdatafactory.c
+++ b/app/core/gimpdatafactory.c
@@ -2,7 +2,7 @@
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  *
  * gimpdatafactory.c
- * Copyright (C) 2001 Michael Natterer <mitch gimp org>
+ * Copyright (C) 2001-2018 Michael Natterer <mitch gimp org>
  *
  * 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
@@ -48,16 +48,27 @@
 #define GIMP_OBSOLETE_DATA_DIR_NAME "gimp-obsolete-files"
 
 
+enum
+{
+  PROP_0,
+  PROP_GIMP,
+  PROP_DATA_TYPE,
+  PROP_PATH_PROPERTY_NAME,
+  PROP_WRITABLE_PROPERTY_NAME
+};
+
+
 typedef void (* GimpDataForeachFunc) (GimpDataFactory *factory,
                                       GimpData        *data,
                                       gpointer         user_data);
 
 
-struct _GimpDataFactoryPriv
+struct _GimpDataFactoryPrivate
 {
   Gimp                             *gimp;
-  GimpContainer                    *container;
 
+  GType                             data_type;
+  GimpContainer                    *container;
   GimpContainer                    *container_obsolete;
 
   gchar                            *path_property_name;
@@ -70,37 +81,71 @@ struct _GimpDataFactoryPriv
   GimpDataGetStandardFunc           data_get_standard_func;
 };
 
-
-static void    gimp_data_factory_finalize       (GObject             *object);
-
-static gint64  gimp_data_factory_get_memsize    (GimpObject          *object,
-                                                 gint64              *gui_size);
-
-static void    gimp_data_factory_data_foreach   (GimpDataFactory     *factory,
-                                                 gboolean             skip_internal,
-                                                 GimpDataForeachFunc  callback,
-                                                 gpointer             user_data);
-
-static void    gimp_data_factory_data_load      (GimpDataFactory     *factory,
-                                                 GimpContext         *context,
-                                                 GHashTable          *cache);
-
-static GFile * gimp_data_factory_get_save_dir   (GimpDataFactory     *factory,
-                                                 GError             **error);
-
-static void    gimp_data_factory_load_directory (GimpDataFactory     *factory,
-                                                 GimpContext         *context,
-                                                 GHashTable          *cache,
-                                                 gboolean             dir_writable,
-                                                 GFile               *directory,
-                                                 GFile               *top_directory);
-static void    gimp_data_factory_load_data      (GimpDataFactory     *factory,
-                                                 GimpContext         *context,
-                                                 GHashTable          *cache,
-                                                 gboolean             dir_writable,
-                                                 GFile               *file,
-                                                 GFileInfo           *info,
-                                                 GFile               *top_directory);
+#define GET_PRIVATE(obj) (((GimpDataFactory *) (obj))->priv)
+
+
+static void       gimp_data_factory_constructed         (GObject             *object);
+static void       gimp_data_factory_set_property        (GObject             *object,
+                                                         guint                property_id,
+                                                         const GValue        *value,
+                                                         GParamSpec          *pspec);
+static void       gimp_data_factory_get_property        (GObject             *object,
+                                                         guint                property_id,
+                                                         GValue              *value,
+                                                         GParamSpec          *pspec);
+static void       gimp_data_factory_finalize            (GObject             *object);
+
+static gint64     gimp_data_factory_get_memsize         (GimpObject          *object,
+                                                         gint64              *gui_size);
+
+static void       gimp_data_factory_real_data_init      (GimpDataFactory     *factory,
+                                                         GimpContext         *context,
+                                                         gboolean             no_data);
+static void       gimp_data_factory_real_data_refresh   (GimpDataFactory     *factory,
+                                                         GimpContext         *context);
+static void       gimp_data_factory_real_data_save      (GimpDataFactory     *factory);
+static void       gimp_data_factory_real_data_free      (GimpDataFactory     *factory);
+static GimpAsyncSet *
+                  gimp_data_factory_real_get_async_set  (GimpDataFactory     *factory);
+static gboolean   gimp_data_factory_real_data_wait      (GimpDataFactory     *factory);
+static GimpData * gimp_data_factory_real_data_new       (GimpDataFactory     *factory,
+                                                         GimpContext         *context,
+                                                         const gchar         *name);
+static GimpData * gimp_data_factory_real_data_duplicate (GimpDataFactory     *factory,
+                                                         GimpData            *data);
+static gboolean   gimp_data_factory_real_data_delete    (GimpDataFactory     *factory,
+                                                         GimpData            *data,
+                                                         gboolean             delete_from_disk,
+                                                         GError             **error);
+
+static void    gimp_data_factory_path_notify            (GObject             *object,
+                                                         const GParamSpec    *pspec,
+                                                         GimpDataFactory     *factory);
+static void    gimp_data_factory_data_foreach           (GimpDataFactory     *factory,
+                                                         gboolean             skip_internal,
+                                                         GimpDataForeachFunc  callback,
+                                                         gpointer             user_data);
+
+static void    gimp_data_factory_data_load              (GimpDataFactory     *factory,
+                                                         GimpContext         *context,
+                                                         GHashTable          *cache);
+
+static GFile * gimp_data_factory_get_save_dir           (GimpDataFactory     *factory,
+                                                         GError             **error);
+
+static void    gimp_data_factory_load_directory         (GimpDataFactory     *factory,
+                                                         GimpContext         *context,
+                                                         GHashTable          *cache,
+                                                         gboolean             dir_writable,
+                                                         GFile               *directory,
+                                                         GFile               *top_directory);
+static void    gimp_data_factory_load_data              (GimpDataFactory     *factory,
+                                                         GimpContext         *context,
+                                                         GHashTable          *cache,
+                                                         gboolean             dir_writable,
+                                                         GFile               *file,
+                                                         GFileInfo           *info,
+                                                         GFile               *top_directory);
 
 
 G_DEFINE_TYPE (GimpDataFactory, gimp_data_factory, GIMP_TYPE_OBJECT)
@@ -114,11 +159,50 @@ gimp_data_factory_class_init (GimpDataFactoryClass *klass)
   GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
   GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
 
+  object_class->constructed      = gimp_data_factory_constructed;
+  object_class->set_property     = gimp_data_factory_set_property;
+  object_class->get_property     = gimp_data_factory_get_property;
   object_class->finalize         = gimp_data_factory_finalize;
 
   gimp_object_class->get_memsize = gimp_data_factory_get_memsize;
 
-  g_type_class_add_private (klass, sizeof (GimpDataFactoryPriv));
+  klass->data_init               = gimp_data_factory_real_data_init;
+  klass->data_refresh            = gimp_data_factory_real_data_refresh;
+  klass->data_save               = gimp_data_factory_real_data_save;
+  klass->data_free               = gimp_data_factory_real_data_free;
+  klass->get_async_set           = gimp_data_factory_real_get_async_set;
+  klass->data_wait               = gimp_data_factory_real_data_wait;
+  klass->data_new                = gimp_data_factory_real_data_new;
+  klass->data_duplicate          = gimp_data_factory_real_data_duplicate;
+  klass->data_delete             = gimp_data_factory_real_data_delete;
+
+  g_object_class_install_property (object_class, PROP_GIMP,
+                                   g_param_spec_object ("gimp", NULL, NULL,
+                                                        GIMP_TYPE_GIMP,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class, PROP_DATA_TYPE,
+                                   g_param_spec_gtype ("data-type", NULL, NULL,
+                                                       GIMP_TYPE_DATA,
+                                                       GIMP_PARAM_READWRITE |
+                                                       G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class, PROP_PATH_PROPERTY_NAME,
+                                   g_param_spec_string ("path-property-name",
+                                                        NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class, PROP_WRITABLE_PROPERTY_NAME,
+                                   g_param_spec_string ("writable-property-name",
+                                                        NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_type_class_add_private (klass, sizeof (GimpDataFactoryPrivate));
 }
 
 static void
@@ -126,106 +210,137 @@ gimp_data_factory_init (GimpDataFactory *factory)
 {
   factory->priv = G_TYPE_INSTANCE_GET_PRIVATE (factory,
                                                GIMP_TYPE_DATA_FACTORY,
-                                               GimpDataFactoryPriv);
-
-  factory->priv->gimp                   = NULL;
-  factory->priv->container              = NULL;
-  factory->priv->container_obsolete     = NULL;
-  factory->priv->path_property_name     = NULL;
-  factory->priv->writable_property_name = NULL;
-  factory->priv->loader_entries         = NULL;
-  factory->priv->n_loader_entries       = 0;
-  factory->priv->data_new_func          = NULL;
-  factory->priv->data_get_standard_func = NULL;
+                                               GimpDataFactoryPrivate);
 }
 
 static void
-gimp_data_factory_finalize (GObject *object)
+gimp_data_factory_constructed (GObject *object)
 {
-  GimpDataFactory *factory = GIMP_DATA_FACTORY (object);
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
 
-  g_clear_object (&factory->priv->container);
-  g_clear_object (&factory->priv->container_obsolete);
+  G_OBJECT_CLASS (parent_class)->constructed (object);
 
-  g_clear_pointer (&factory->priv->path_property_name,     g_free);
-  g_clear_pointer (&factory->priv->writable_property_name, g_free);
+  gimp_assert (GIMP_IS_GIMP (priv->gimp));
+  gimp_assert (g_type_is_a (priv->data_type, GIMP_TYPE_DATA));
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  priv->container = gimp_list_new (priv->data_type, TRUE);
+  gimp_list_set_sort_func (GIMP_LIST (priv->container),
+                           (GCompareFunc) gimp_data_compare);
+
+  priv->container_obsolete = gimp_list_new (priv->data_type, TRUE);
+  gimp_list_set_sort_func (GIMP_LIST (priv->container_obsolete),
+                           (GCompareFunc) gimp_data_compare);
 }
 
-static gint64
-gimp_data_factory_get_memsize (GimpObject *object,
-                               gint64     *gui_size)
+static void
+gimp_data_factory_set_property (GObject      *object,
+                                guint         property_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
 {
-  GimpDataFactory *factory = GIMP_DATA_FACTORY (object);
-  gint64           memsize = 0;
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
 
-  memsize += gimp_object_get_memsize (GIMP_OBJECT (factory->priv->container),
-                                      gui_size);
-  memsize += gimp_object_get_memsize (GIMP_OBJECT (factory->priv->container_obsolete),
-                                      gui_size);
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      priv->gimp = g_value_get_object (value); /* don't ref */
+      break;
 
-  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
-                                                                  gui_size);
+    case PROP_DATA_TYPE:
+      priv->data_type = g_value_get_gtype (value);
+      break;
+
+    case PROP_PATH_PROPERTY_NAME:
+      priv->path_property_name = g_value_dup_string (value);
+      break;
+
+    case PROP_WRITABLE_PROPERTY_NAME:
+      priv->writable_property_name = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
 }
 
-GimpDataFactory *
-gimp_data_factory_new (Gimp                             *gimp,
-                       GType                             data_type,
-                       const gchar                      *path_property_name,
-                       const gchar                      *writable_property_name,
-                       const GimpDataFactoryLoaderEntry *loader_entries,
-                       gint                              n_loader_entries,
-                       GimpDataNewFunc                   new_func,
-                       GimpDataGetStandardFunc           get_standard_func)
+static void
+gimp_data_factory_get_property (GObject    *object,
+                                guint       property_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
 {
-  GimpDataFactory *factory;
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
 
-  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
-  g_return_val_if_fail (g_type_is_a (data_type, GIMP_TYPE_DATA), NULL);
-  g_return_val_if_fail (path_property_name != NULL, NULL);
-  g_return_val_if_fail (writable_property_name != NULL, NULL);
-  g_return_val_if_fail (loader_entries != NULL, NULL);
-  g_return_val_if_fail (n_loader_entries > 0, NULL);
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      g_value_set_object (value, priv->gimp);
+      break;
 
-  factory = g_object_new (GIMP_TYPE_DATA_FACTORY, NULL);
+    case PROP_DATA_TYPE:
+      g_value_set_gtype (value, priv->data_type);
+      break;
 
-  factory->priv->gimp                   = gimp;
-  factory->priv->container              = gimp_list_new (data_type, TRUE);
-  gimp_list_set_sort_func (GIMP_LIST (factory->priv->container),
-                           (GCompareFunc) gimp_data_compare);
-  factory->priv->container_obsolete     = gimp_list_new (data_type, TRUE);
-  gimp_list_set_sort_func (GIMP_LIST (factory->priv->container_obsolete),
-                           (GCompareFunc) gimp_data_compare);
+    case PROP_PATH_PROPERTY_NAME:
+      g_value_set_string (value, priv->path_property_name);
+      break;
 
-  factory->priv->path_property_name     = g_strdup (path_property_name);
-  factory->priv->writable_property_name = g_strdup (writable_property_name);
+    case PROP_WRITABLE_PROPERTY_NAME:
+      g_value_set_string (value, priv->writable_property_name);
+      break;
 
-  factory->priv->loader_entries         = loader_entries;
-  factory->priv->n_loader_entries       = n_loader_entries;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
 
-  factory->priv->data_new_func          = new_func;
-  factory->priv->data_get_standard_func = get_standard_func;
+static void
+gimp_data_factory_finalize (GObject *object)
+{
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (object);
 
-  return factory;
+  g_clear_object (&priv->container);
+  g_clear_object (&priv->container_obsolete);
+
+  g_clear_pointer (&priv->path_property_name,     g_free);
+  g_clear_pointer (&priv->writable_property_name, g_free);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-void
-gimp_data_factory_data_init (GimpDataFactory *factory,
-                             GimpContext     *context,
-                             gboolean         no_data)
+static gint64
+gimp_data_factory_get_memsize (GimpObject *object,
+                               gint64     *gui_size)
 {
-  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
-  g_return_if_fail (GIMP_IS_CONTEXT (context));
+  GimpDataFactoryPrivate *priv    = GET_PRIVATE (object);
+  gint64                  memsize = 0;
+
+  memsize += gimp_object_get_memsize (GIMP_OBJECT (priv->container),
+                                      gui_size);
+  memsize += gimp_object_get_memsize (GIMP_OBJECT (priv->container_obsolete),
+                                      gui_size);
+
+  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+                                                                  gui_size);
+}
+
+static void
+gimp_data_factory_real_data_init (GimpDataFactory *factory,
+                                  GimpContext     *context,
+                                  gboolean         no_data)
+{
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
 
   /*  Freeze and thaw the container even if no_data,
    *  this creates the standard data that serves as fallback.
    */
-  gimp_container_freeze (factory->priv->container);
+  gimp_container_freeze (priv->container);
 
   if (! no_data)
     {
-      if (factory->priv->gimp->be_verbose)
+      if (priv->gimp->be_verbose)
         {
           const gchar *name = gimp_object_get_name (factory);
 
@@ -235,25 +350,7 @@ gimp_data_factory_data_init (GimpDataFactory *factory,
       gimp_data_factory_data_load (factory, context, NULL);
     }
 
-  gimp_container_thaw (factory->priv->container);
-}
-
-static void
-gimp_data_factory_clean_cb (GimpDataFactory *factory,
-                            GimpData        *data,
-                            gpointer         user_data)
-{
-  if (gimp_data_is_dirty (data))
-    gimp_data_clean (data);
-}
-
-void
-gimp_data_factory_data_clean (GimpDataFactory *factory)
-{
-  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
-
-  gimp_data_factory_data_foreach (factory, TRUE,
-                                  gimp_data_factory_clean_cb, NULL);
+  gimp_container_thaw (priv->container);
 }
 
 static void
@@ -295,79 +392,13 @@ gimp_data_factory_refresh_cache_remove (gpointer key,
 }
 
 static void
-gimp_data_factory_data_foreach (GimpDataFactory     *factory,
-                                gboolean             skip_internal,
-                                GimpDataForeachFunc  callback,
-                                gpointer             user_data)
-{
-  GList *list = GIMP_LIST (factory->priv->container)->queue->head;
-
-  if (skip_internal)
-    {
-      while (list && gimp_data_is_internal (GIMP_DATA (list->data)))
-        list = g_list_next (list);
-    }
-
-  while (list)
-    {
-      GList *next = g_list_next (list);
-
-      callback (factory, list->data, user_data);
-
-      list = next;
-    }
-}
-
-static void
-gimp_data_factory_data_load (GimpDataFactory *factory,
-                             GimpContext     *context,
-                             GHashTable      *cache)
-{
-  gchar *p;
-  gchar *wp;
-  GList *path;
-  GList *writable_path;
-  GList *list;
-
-  g_object_get (factory->priv->gimp->config,
-                factory->priv->path_property_name,     &p,
-                factory->priv->writable_property_name, &wp,
-                NULL);
-
-  path          = gimp_config_path_expand_to_files (p, NULL);
-  writable_path = gimp_config_path_expand_to_files (wp, NULL);
-
-  g_free (p);
-  g_free (wp);
-
-  for (list = path; list; list = g_list_next (list))
-    {
-      gboolean dir_writable = FALSE;
-
-      if (g_list_find_custom (writable_path, list->data,
-                              (GCompareFunc) gimp_file_compare))
-        dir_writable = TRUE;
-
-      gimp_data_factory_load_directory (factory, context, cache,
-                                        dir_writable,
-                                        list->data,
-                                        list->data);
-    }
-
-  g_list_free_full (path,          (GDestroyNotify) g_object_unref);
-  g_list_free_full (writable_path, (GDestroyNotify) g_object_unref);
-}
-
-void
-gimp_data_factory_data_refresh (GimpDataFactory *factory,
-                                GimpContext     *context)
+gimp_data_factory_real_data_refresh (GimpDataFactory *factory,
+                                     GimpContext     *context)
 {
-  GHashTable *cache;
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
+  GHashTable             *cache;
 
-  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
-  g_return_if_fail (GIMP_IS_CONTEXT (context));
-
-  gimp_container_freeze (factory->priv->container);
+  gimp_container_freeze (priv->container);
 
   /*  First, save all dirty data objects  */
   gimp_data_factory_data_save (factory);
@@ -393,23 +424,19 @@ gimp_data_factory_data_refresh (GimpDataFactory *factory,
 
   g_hash_table_destroy (cache);
 
-  gimp_container_thaw (factory->priv->container);
+  gimp_container_thaw (priv->container);
 }
 
-void
-gimp_data_factory_data_save (GimpDataFactory *factory)
+static void
+gimp_data_factory_real_data_save (GimpDataFactory *factory)
 {
-  GList  *dirty = NULL;
-  GList  *list;
-  GFile  *writable_dir;
-  GError *error = NULL;
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
+  GList                  *dirty = NULL;
+  GList                  *list;
+  GFile                  *writable_dir;
+  GError                 *error = NULL;
 
-  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
-
-  if (gimp_container_is_empty (factory->priv->container))
-    return;
-
-  for (list = GIMP_LIST (factory->priv->container)->queue->head;
+  for (list = GIMP_LIST (priv->container)->queue->head;
        list;
        list = g_list_next (list))
     {
@@ -429,7 +456,7 @@ gimp_data_factory_data_save (GimpDataFactory *factory)
 
   if (! writable_dir)
     {
-      gimp_message (factory->priv->gimp, NULL, GIMP_MESSAGE_ERROR,
+      gimp_message (priv->gimp, NULL, GIMP_MESSAGE_ERROR,
                     _("Failed to save data:\n\n%s"),
                     error->message);
       g_clear_error (&error);
@@ -454,7 +481,7 @@ gimp_data_factory_data_save (GimpDataFactory *factory)
            */
           if (error)
             {
-              gimp_message (factory->priv->gimp, NULL, GIMP_MESSAGE_ERROR,
+              gimp_message (priv->gimp, NULL, GIMP_MESSAGE_ERROR,
                             _("Failed to save data:\n\n%s"),
                             error->message);
               g_clear_error (&error);
@@ -475,11 +502,9 @@ gimp_data_factory_remove_cb (GimpDataFactory *factory,
   gimp_container_remove (factory->priv->container, GIMP_OBJECT (data));
 }
 
-void
-gimp_data_factory_data_free (GimpDataFactory *factory)
+static void
+gimp_data_factory_real_data_free (GimpDataFactory *factory)
 {
-  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
-
   gimp_container_freeze (factory->priv->container);
 
   gimp_data_factory_data_foreach (factory, TRUE,
@@ -488,42 +513,50 @@ gimp_data_factory_data_free (GimpDataFactory *factory)
   gimp_container_thaw (factory->priv->container);
 }
 
-GimpData *
-gimp_data_factory_data_new (GimpDataFactory *factory,
-                            GimpContext     *context,
-                            const gchar     *name)
+static GimpAsyncSet *
+gimp_data_factory_real_get_async_set (GimpDataFactory *factory)
 {
-  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
-  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
-  g_return_val_if_fail (name != NULL, NULL);
-  g_return_val_if_fail (*name != '\0', NULL);
+  return NULL;
+}
 
-  if (factory->priv->data_new_func)
+static gboolean
+gimp_data_factory_real_data_wait (GimpDataFactory *factory)
+{
+  return TRUE;
+}
+
+static GimpData *
+gimp_data_factory_real_data_new (GimpDataFactory *factory,
+                                 GimpContext     *context,
+                                 const gchar     *name)
+{
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
+
+  if (priv->data_new_func)
     {
-      GimpData *data = factory->priv->data_new_func (context, name);
+      GimpData *data = priv->data_new_func (context, name);
 
       if (data)
         {
-          gimp_container_add (factory->priv->container, GIMP_OBJECT (data));
+          gimp_container_add (priv->container, GIMP_OBJECT (data));
           g_object_unref (data);
 
           return data;
         }
 
-      g_warning ("%s: factory->priv->data_new_func() returned NULL", G_STRFUNC);
+      g_warning ("%s: GimpDataFactory::data_new_func() returned NULL",
+                 G_STRFUNC);
     }
 
   return NULL;
 }
 
-GimpData *
-gimp_data_factory_data_duplicate (GimpDataFactory *factory,
-                                  GimpData        *data)
+static GimpData *
+gimp_data_factory_real_data_duplicate (GimpDataFactory *factory,
+                                       GimpData        *data)
 {
-  GimpData *new_data;
-
-  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
-  g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
+  GimpData               *new_data;
 
   new_data = gimp_data_duplicate (data);
 
@@ -553,30 +586,27 @@ gimp_data_factory_data_duplicate (GimpDataFactory *factory,
 
       gimp_object_take_name (GIMP_OBJECT (new_data), new_name);
 
-      gimp_container_add (factory->priv->container, GIMP_OBJECT (new_data));
+      gimp_container_add (priv->container, GIMP_OBJECT (new_data));
       g_object_unref (new_data);
     }
 
   return new_data;
 }
 
-gboolean
-gimp_data_factory_data_delete (GimpDataFactory  *factory,
-                               GimpData         *data,
-                               gboolean          delete_from_disk,
-                               GError          **error)
+static gboolean
+gimp_data_factory_real_data_delete (GimpDataFactory  *factory,
+                                    GimpData         *data,
+                                    gboolean          delete_from_disk,
+                                    GError          **error)
 {
-  gboolean retval = TRUE;
+  GimpDataFactoryPrivate *priv   = GET_PRIVATE (factory);
+  gboolean                retval = TRUE;
 
-  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
-  g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  if (gimp_container_have (factory->priv->container, GIMP_OBJECT (data)))
+  if (gimp_container_have (priv->container, GIMP_OBJECT (data)))
     {
       g_object_ref (data);
 
-      gimp_container_remove (factory->priv->container, GIMP_OBJECT (data));
+      gimp_container_remove (priv->container, GIMP_OBJECT (data));
 
       if (delete_from_disk && gimp_data_get_file (data))
         retval = gimp_data_delete_from_disk (data, error);
@@ -587,6 +617,165 @@ gimp_data_factory_data_delete (GimpDataFactory  *factory,
   return retval;
 }
 
+
+/*  public functions  */
+
+GimpDataFactory *
+gimp_data_factory_new (Gimp                             *gimp,
+                       GType                             data_type,
+                       const gchar                      *path_property_name,
+                       const gchar                      *writable_property_name,
+                       const GimpDataFactoryLoaderEntry *loader_entries,
+                       gint                              n_loader_entries,
+                       GimpDataNewFunc                   new_func,
+                       GimpDataGetStandardFunc           get_standard_func)
+{
+  GimpDataFactory *factory;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+  g_return_val_if_fail (g_type_is_a (data_type, GIMP_TYPE_DATA), NULL);
+  g_return_val_if_fail (path_property_name != NULL, NULL);
+  g_return_val_if_fail (writable_property_name != NULL, NULL);
+  g_return_val_if_fail (loader_entries != NULL, NULL);
+  g_return_val_if_fail (n_loader_entries > 0, NULL);
+
+  factory = g_object_new (GIMP_TYPE_DATA_FACTORY,
+                          "gimp",                   gimp,
+                          "data-type",              data_type,
+                          "path-property-name",     path_property_name,
+                          "writable-property-name", writable_property_name,
+                          NULL);
+
+  factory->priv->loader_entries         = loader_entries;
+  factory->priv->n_loader_entries       = n_loader_entries;
+
+  factory->priv->data_new_func          = new_func;
+  factory->priv->data_get_standard_func = get_standard_func;
+
+  return factory;
+}
+
+void
+gimp_data_factory_data_init (GimpDataFactory *factory,
+                             GimpContext     *context,
+                             gboolean         no_data)
+{
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
+  gchar                  *signal_name;
+
+  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
+  g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+  GIMP_DATA_FACTORY_GET_CLASS (factory)->data_init (factory, context, no_data);
+
+  signal_name = g_strdup_printf ("notify::%s", priv->path_property_name);
+  g_signal_connect_object (priv->gimp->config, signal_name,
+                           G_CALLBACK (gimp_data_factory_path_notify),
+                           factory, 0);
+  g_free (signal_name);
+}
+
+static void
+gimp_data_factory_clean_cb (GimpDataFactory *factory,
+                            GimpData        *data,
+                            gpointer         user_data)
+{
+  if (gimp_data_is_dirty (data))
+    gimp_data_clean (data);
+}
+
+void
+gimp_data_factory_data_clean (GimpDataFactory *factory)
+{
+  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
+
+  gimp_data_factory_data_foreach (factory, TRUE,
+                                  gimp_data_factory_clean_cb, NULL);
+}
+
+void
+gimp_data_factory_data_refresh (GimpDataFactory *factory,
+                                GimpContext     *context)
+{
+  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
+  g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+  GIMP_DATA_FACTORY_GET_CLASS (factory)->data_refresh (factory, context);
+}
+
+void
+gimp_data_factory_data_save (GimpDataFactory *factory)
+{
+  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
+
+  if (! gimp_container_is_empty (factory->priv->container))
+    GIMP_DATA_FACTORY_GET_CLASS (factory)->data_save (factory);
+}
+
+void
+gimp_data_factory_data_free (GimpDataFactory *factory)
+{
+  g_return_if_fail (GIMP_IS_DATA_FACTORY (factory));
+
+  if (! gimp_container_is_empty (factory->priv->container))
+    GIMP_DATA_FACTORY_GET_CLASS (factory)->data_free (factory);
+}
+
+GimpAsyncSet *
+gimp_data_factory_get_async_set (GimpDataFactory *factory)
+{
+  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
+
+  return GIMP_DATA_FACTORY_GET_CLASS (factory)->get_async_set (factory);
+}
+
+gboolean
+gimp_data_factory_data_wait (GimpDataFactory *factory)
+{
+  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
+
+  return GIMP_DATA_FACTORY_GET_CLASS (factory)->data_wait (factory);
+}
+
+GimpData *
+gimp_data_factory_data_new (GimpDataFactory *factory,
+                            GimpContext     *context,
+                            const gchar     *name)
+{
+  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
+  g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (*name != '\0', NULL);
+
+  return GIMP_DATA_FACTORY_GET_CLASS (factory)->data_new (factory, context,
+                                                          name);
+}
+
+GimpData *
+gimp_data_factory_data_duplicate (GimpDataFactory *factory,
+                                  GimpData        *data)
+{
+  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), NULL);
+  g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
+
+  return GIMP_DATA_FACTORY_GET_CLASS (factory)->data_duplicate (factory, data);
+}
+
+gboolean
+gimp_data_factory_data_delete (GimpDataFactory  *factory,
+                               GimpData         *data,
+                               gboolean          delete_from_disk,
+                               GError          **error)
+{
+  g_return_val_if_fail (GIMP_IS_DATA_FACTORY (factory), FALSE);
+  g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  return GIMP_DATA_FACTORY_GET_CLASS (factory)->data_delete (factory, data,
+                                                             delete_from_disk,
+                                                             error);
+}
+
 GimpData *
 gimp_data_factory_data_get_standard (GimpDataFactory *factory,
                                      GimpContext     *context)
@@ -696,6 +885,84 @@ gimp_data_factory_has_data_new_func (GimpDataFactory *factory)
 
 /*  private functions  */
 
+static void
+gimp_data_factory_path_notify (GObject          *object,
+                               const GParamSpec *pspec,
+                               GimpDataFactory  *factory)
+{
+  GimpDataFactoryPrivate *priv = GET_PRIVATE (factory);
+
+  gimp_set_busy (priv->gimp);
+
+  gimp_data_factory_data_refresh (factory, gimp_get_user_context (priv->gimp));
+
+  gimp_unset_busy (priv->gimp);
+}
+
+static void
+gimp_data_factory_data_foreach (GimpDataFactory     *factory,
+                                gboolean             skip_internal,
+                                GimpDataForeachFunc  callback,
+                                gpointer             user_data)
+{
+  GList *list = GIMP_LIST (factory->priv->container)->queue->head;
+
+  if (skip_internal)
+    {
+      while (list && gimp_data_is_internal (GIMP_DATA (list->data)))
+        list = g_list_next (list);
+    }
+
+  while (list)
+    {
+      GList *next = g_list_next (list);
+
+      callback (factory, list->data, user_data);
+
+      list = next;
+    }
+}
+
+static void
+gimp_data_factory_data_load (GimpDataFactory *factory,
+                             GimpContext     *context,
+                             GHashTable      *cache)
+{
+  gchar *p;
+  gchar *wp;
+  GList *path;
+  GList *writable_path;
+  GList *list;
+
+  g_object_get (factory->priv->gimp->config,
+                factory->priv->path_property_name,     &p,
+                factory->priv->writable_property_name, &wp,
+                NULL);
+
+  path          = gimp_config_path_expand_to_files (p, NULL);
+  writable_path = gimp_config_path_expand_to_files (wp, NULL);
+
+  g_free (p);
+  g_free (wp);
+
+  for (list = path; list; list = g_list_next (list))
+    {
+      gboolean dir_writable = FALSE;
+
+      if (g_list_find_custom (writable_path, list->data,
+                              (GCompareFunc) gimp_file_compare))
+        dir_writable = TRUE;
+
+      gimp_data_factory_load_directory (factory, context, cache,
+                                        dir_writable,
+                                        list->data,
+                                        list->data);
+    }
+
+  g_list_free_full (path,          (GDestroyNotify) g_object_unref);
+  g_list_free_full (writable_path, (GDestroyNotify) g_object_unref);
+}
+
 static GFile *
 gimp_data_factory_get_save_dir (GimpDataFactory  *factory,
                                 GError          **error)
diff --git a/app/core/gimpdatafactory.h b/app/core/gimpdatafactory.h
index 8456464828..8e1abcaf90 100644
--- a/app/core/gimpdatafactory.h
+++ b/app/core/gimpdatafactory.h
@@ -2,7 +2,7 @@
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  *
  * gimpdatafactory.h
- * Copyright (C) 2001 Michael Natterer <mitch gimp org>
+ * Copyright (C) 2001-2018 Michael Natterer <mitch gimp org>
  *
  * 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
@@ -52,19 +52,40 @@ struct _GimpDataFactoryLoaderEntry
 #define GIMP_DATA_FACTORY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DATA_FACTORY, 
GimpDataFactoryClass))
 
 
-typedef struct _GimpDataFactoryClass  GimpDataFactoryClass;
-typedef struct _GimpDataFactoryPriv   GimpDataFactoryPriv;
+typedef struct _GimpDataFactoryPrivate GimpDataFactoryPrivate;
+typedef struct _GimpDataFactoryClass   GimpDataFactoryClass;
 
 struct _GimpDataFactory
 {
-  GimpObject           parent_instance;
+  GimpObject              parent_instance;
 
-  GimpDataFactoryPriv *priv;
+  GimpDataFactoryPrivate *priv;
 };
 
 struct _GimpDataFactoryClass
 {
   GimpObjectClass  parent_class;
+
+  void           (* data_init)      (GimpDataFactory *factory,
+                                     GimpContext     *context,
+                                     gboolean         no_data);
+  void           (* data_refresh)   (GimpDataFactory *factory,
+                                     GimpContext     *context);
+  void           (* data_save)      (GimpDataFactory *factory);
+  void           (* data_free)      (GimpDataFactory *factory);
+
+  GimpAsyncSet * (* get_async_set) (GimpDataFactory *factory);
+  gboolean       (* data_wait)     (GimpDataFactory *factory);
+
+  GimpData     * (* data_new)       (GimpDataFactory  *factory,
+                                     GimpContext      *context,
+                                     const gchar      *name);
+  GimpData     * (* data_duplicate) (GimpDataFactory  *factory,
+                                     GimpData         *data);
+  gboolean       (* data_delete)    (GimpDataFactory  *factory,
+                                     GimpData         *data,
+                                     gboolean          delete_from_disk,
+                                     GError          **error);
 };
 
 
@@ -88,6 +109,9 @@ void            gimp_data_factory_data_refresh      (GimpDataFactory  *factory,
 void            gimp_data_factory_data_save         (GimpDataFactory  *factory);
 void            gimp_data_factory_data_free         (GimpDataFactory  *factory);
 
+GimpAsyncSet  * gimp_data_factory_get_async_set     (GimpDataFactory  *factory);
+gboolean        gimp_data_factory_data_wait         (GimpDataFactory  *factory);
+
 GimpData      * gimp_data_factory_data_new          (GimpDataFactory  *factory,
                                                      GimpContext      *context,
                                                      const gchar      *name);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]