[gimp] app: port GimpDataFactory file loading to GFileEnumerator



commit 6821eb298c1464f1b682fd94f5890b5b5529f81f
Author: Michael Natterer <mitch gimp org>
Date:   Fri Aug 1 20:30:45 2014 +0200

    app: port GimpDataFactory file loading to GFileEnumerator
    
    Also slightly change the semantics of gimp_data_set_folder_tags()
    to be less complicated.

 app/core/gimpdata.c        |   63 ++++++------
 app/core/gimpdata.h        |    2 +-
 app/core/gimpdatafactory.c |  240 ++++++++++++++++++++++++--------------------
 3 files changed, 161 insertions(+), 144 deletions(-)
---
diff --git a/app/core/gimpdata.c b/app/core/gimpdata.c
index 69171cf..409b1ab 100644
--- a/app/core/gimpdata.c
+++ b/app/core/gimpdata.c
@@ -929,26 +929,28 @@ static const gchar *tag_blacklist[] = { "brushes",
  * gimp_data_set_folder_tags:
  * @data:          a #Gimpdata object.
  * @top_directory: the top directory of the currently processed data
- *                 hierarchy, or %NULL if that top directory is
- *                 currently processed itself
+ *                 hierarchy.
  *
  * Sets tags based on all folder names below top_directory. So if the
- * data's filename is /home/foo/.gimp/brushes/Flowers/Roses/rose.gbr,
- * it will add "Flowers" and "Roses" tags.
+ * data's filename is e.g.
+ * /home/foo/.config/GIMP/X.Y/brushes/Flowers/Roses/rose.gbr, it will
+ * add "Flowers" and "Roses" tags.
  *
  * if the top directory (as passed, or as derived from the data's
  * filename) does not end with one of the default data directory names
  * (brushes, patterns etc), its name will be added as tag too.
  **/
 void
-gimp_data_set_folder_tags (GimpData    *data,
-                           const gchar *top_directory)
+gimp_data_set_folder_tags (GimpData *data,
+                           GFile    *top_directory)
 {
   GimpDataPrivate *private;
-  gchar           *path;
+  gchar           *tmp;
   gchar           *dirname;
+  gchar           *top_path;
 
   g_return_if_fail (GIMP_IS_DATA (data));
+  g_return_if_fail (G_IS_FILE (top_directory));
 
   private = GIMP_DATA_GET_PRIVATE (data);
 
@@ -957,39 +959,34 @@ gimp_data_set_folder_tags (GimpData    *data,
 
   g_return_if_fail (private->file != NULL);
 
-  path    = g_file_get_path (private->file);
-  dirname = g_path_get_dirname (path);
-  g_free (path);
+  tmp = g_file_get_path (private->file);
+  dirname = g_path_get_dirname (tmp);
+  g_free (tmp);
 
-  /*  if this data is in a subfolder, walk up the hierarchy and
-   *  set each folder on the way as tag, except the top_directory
-   */
-  if (top_directory)
-    {
-      size_t top_directory_len = strlen (top_directory);
+  top_path = g_file_get_path (top_directory);
 
-      g_return_if_fail (g_str_has_prefix (dirname, top_directory) &&
-                        (dirname[top_directory_len] == '\0' ||
-                         G_IS_DIR_SEPARATOR (dirname[top_directory_len])));
+  g_return_if_fail (g_str_has_prefix (dirname, top_path));
 
-      do
-        {
-          gchar   *basename = g_path_get_basename (dirname);
-          GimpTag *tag      = gimp_tag_new (basename);
-          gchar   *tmp;
+  /*  walk up the hierarchy and set each folder on the way as tag,
+   *  except the top_directory
+   */
+  while (strcmp (dirname, top_path))
+    {
+      gchar   *basename = g_path_get_basename (dirname);
+      GimpTag *tag      = gimp_tag_new (basename);
 
-          gimp_tag_set_internal (tag, TRUE);
-          gimp_tagged_add_tag (GIMP_TAGGED (data), tag);
-          g_object_unref (tag);
-          g_free (basename);
+      gimp_tag_set_internal (tag, TRUE);
+      gimp_tagged_add_tag (GIMP_TAGGED (data), tag);
+      g_object_unref (tag);
+      g_free (basename);
 
-          tmp = g_path_get_dirname (dirname);
-          g_free (dirname);
-          dirname = tmp;
-        }
-      while (strcmp (dirname, top_directory));
+      tmp = g_path_get_dirname (dirname);
+      g_free (dirname);
+      dirname = tmp;
     }
 
+  g_free (top_path);
+
   if (dirname)
     {
       gchar *basename = g_path_get_basename (dirname);
diff --git a/app/core/gimpdata.h b/app/core/gimpdata.h
index ec7baf8..77454ce 100644
--- a/app/core/gimpdata.h
+++ b/app/core/gimpdata.h
@@ -93,7 +93,7 @@ void          gimp_data_create_filename  (GimpData     *data,
                                           GFile        *dest_dir);
 
 void          gimp_data_set_folder_tags  (GimpData     *data,
-                                          const gchar  *top_directory);
+                                          GFile        *top_directory);
 
 const gchar * gimp_data_get_mime_type    (GimpData     *data);
 
diff --git a/app/core/gimpdatafactory.c b/app/core/gimpdatafactory.c
index c0b000a..a62da4d 100644
--- a/app/core/gimpdatafactory.c
+++ b/app/core/gimpdatafactory.c
@@ -70,23 +70,32 @@ struct _GimpDataFactoryPriv
 };
 
 
-static void    gimp_data_factory_finalize     (GObject              *object);
+static void    gimp_data_factory_finalize       (GObject          *object);
 
-static void    gimp_data_factory_data_load    (GimpDataFactory      *factory,
-                                               GimpContext          *context,
-                                               GHashTable           *cache);
+static gint64  gimp_data_factory_get_memsize    (GimpObject       *object,
+                                                 gint64           *gui_size);
 
-static gint64  gimp_data_factory_get_memsize  (GimpObject           *object,
-                                               gint64               *gui_size);
+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 GFile * gimp_data_factory_get_save_dir   (GimpDataFactory  *factory,
+                                                 GError          **error);
 
-static void    gimp_data_factory_load_data  (const GimpDatafileData *file_data,
-                                             gpointer                data);
+static void    gimp_data_factory_load_directory (GimpDataFactory  *factory,
+                                                 GimpContext      *context,
+                                                 GHashTable       *cache,
+                                                 GList            *writable_path,
+                                                 GFile            *directory,
+                                                 GFile            *top_directory);
+static void    gimp_data_factory_load_data      (GimpDataFactory  *factory,
+                                                 GimpContext      *context,
+                                                 GHashTable       *cache,
+                                                 GList            *writable_path,
+                                                 GFile            *file,
+                                                 guint64           mtime,
+                                                 GFile            *top_directory);
 
-static void    gimp_data_factory_load_data_recursive (const GimpDatafileData *file_data,
-                                                      gpointer                data);
 
 G_DEFINE_TYPE (GimpDataFactory, gimp_data_factory, GIMP_TYPE_OBJECT)
 
@@ -303,67 +312,38 @@ gimp_data_factory_data_foreach (GimpDataFactory     *factory,
     }
 }
 
-typedef struct
-{
-  GimpDataFactory *factory;
-  GimpContext     *context;
-  GHashTable      *cache;
-  const gchar     *top_directory;
-  GList           *writable_path;
-} GimpDataLoadContext;
-
 static void
 gimp_data_factory_data_load (GimpDataFactory *factory,
                              GimpContext     *context,
                              GHashTable      *cache)
 {
-  gchar *path;
-  gchar *writable_path;
+  gchar *p;
+  gchar *wp;
+  GList *path;
+  GList *writable_path;
+  GList *list;
 
   g_object_get (factory->priv->gimp->config,
-                factory->priv->path_property_name,     &path,
-                factory->priv->writable_property_name, &writable_path,
+                factory->priv->path_property_name,     &p,
+                factory->priv->writable_property_name, &wp,
                 NULL);
 
-  if (path && strlen (path))
-    {
-      GimpDataLoadContext  load_context = { 0, };
-      gchar               *tmp;
-
-      load_context.factory = factory;
-      load_context.context = context;
-      load_context.cache   = cache;
-
-      tmp = gimp_config_path_expand (path, TRUE, NULL);
-      g_free (path);
-      path = tmp;
-
-      if (writable_path)
-        {
-          tmp = gimp_config_path_expand (writable_path, TRUE, NULL);
-          g_free (writable_path);
-          writable_path = tmp;
-
-          load_context.writable_path = gimp_path_parse (writable_path,
-                                                        256, TRUE, NULL);
-        }
-
-      gimp_datafiles_read_directories (path, G_FILE_TEST_IS_REGULAR,
-                                       gimp_data_factory_load_data,
-                                       &load_context);
+  path          = gimp_config_path_expand_to_files (p, NULL);
+  writable_path = gimp_config_path_expand_to_files (wp, NULL);
 
-      gimp_datafiles_read_directories (path, G_FILE_TEST_IS_DIR,
-                                       gimp_data_factory_load_data_recursive,
-                                       &load_context);
+  g_free (p);
+  g_free (wp);
 
-      if (writable_path)
-        {
-          gimp_path_free (load_context.writable_path);
-        }
+  for (list = path; list; list = g_list_next (list))
+    {
+      gimp_data_factory_load_directory (factory, context, cache,
+                                        writable_path,
+                                        list->data,
+                                        list->data);
     }
 
-  g_free (path);
-  g_free (writable_path);
+  g_list_free_full (path, (GDestroyNotify) g_object_unref);
+  g_list_free_full (writable_path, (GDestroyNotify) g_object_unref);
 }
 
 void
@@ -793,67 +773,109 @@ gimp_data_factory_get_save_dir (GimpDataFactory  *factory,
 }
 
 static gboolean
-gimp_data_factory_is_dir_writable (const gchar *dirname,
+gimp_data_factory_is_dir_writable (const gchar *uri,
                                    GList       *writable_path)
 {
   GList *list;
 
   for (list = writable_path; list; list = g_list_next (list))
     {
-      if (g_str_has_prefix (dirname, list->data))
-        return TRUE;
+      gchar *path_uri = g_file_get_uri (list->data);
+
+      if (g_str_has_prefix (uri, path_uri))
+        {
+          g_free (path_uri);
+          return TRUE;
+        }
+
+      g_free (path_uri);
     }
 
   return FALSE;
 }
 
 static void
-gimp_data_factory_load_data_recursive (const GimpDatafileData *file_data,
-                                       gpointer                data)
+gimp_data_factory_load_directory (GimpDataFactory *factory,
+                                  GimpContext     *context,
+                                  GHashTable      *cache,
+                                  GList           *writable_path,
+                                  GFile           *directory,
+                                  GFile           *top_directory)
 {
-  GimpDataLoadContext *context = data;
-  gboolean             top_set = FALSE;
-
-  /*  When processing subdirectories, set the top_directory if it's
-   *  unset. This way me make sure gimp_data_set_folder_tags()'
-   *  calling convention is honored: pass NULL when processing the
-   *  toplevel directory itself, and pass the toplevel directory when
-   *  processing any folder inside.
-   */
-  if (! context->top_directory)
+  GFileEnumerator *enumerator;
+
+  enumerator = g_file_enumerate_children (directory,
+                                          G_FILE_ATTRIBUTE_STANDARD_NAME ","
+                                          G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+                                          G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+                                          G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                                          G_FILE_QUERY_INFO_NONE,
+                                          NULL, NULL);
+
+  if (enumerator)
     {
-      context->top_directory = file_data->dirname;
-      top_set = TRUE;
-    }
+      GFileInfo *info;
 
-  gimp_datafiles_read_directories (file_data->filename, G_FILE_TEST_IS_REGULAR,
-                                   gimp_data_factory_load_data, context);
+      while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
+        {
+          GFileType  file_type;
+          GFile     *child;
 
-  gimp_datafiles_read_directories (file_data->filename, G_FILE_TEST_IS_DIR,
-                                   gimp_data_factory_load_data_recursive,
-                                   context);
+          if (g_file_info_get_is_hidden (info))
+            {
+              g_object_unref (info);
+              continue;
+            }
 
-  /*  Unset, the string is only valid within this function, and will
-   *  be set again for the next subdirectory.
-   */
-  if (top_set)
-    context->top_directory = NULL;
+          file_type = g_file_info_get_file_type (info);
+          child     = g_file_enumerator_get_child (enumerator, info);
+
+          if (file_type == G_FILE_TYPE_DIRECTORY)
+            {
+              gimp_data_factory_load_directory (factory, context, cache,
+                                                writable_path,
+                                                child,
+                                                top_directory);
+            }
+          else if (file_type == G_FILE_TYPE_REGULAR)
+            {
+              guint64 mtime;
+
+              mtime = g_file_info_get_attribute_uint64 (info,
+                                                        G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+              gimp_data_factory_load_data (factory, context, cache,
+                                           writable_path,
+                                           child, mtime,
+                                           top_directory);
+            }
+
+          g_object_unref (child);
+          g_object_unref (info);
+        }
+
+      g_object_unref (enumerator);
+    }
 }
 
 static void
-gimp_data_factory_load_data (const GimpDatafileData *file_data,
-                             gpointer                data)
+gimp_data_factory_load_data (GimpDataFactory *factory,
+                             GimpContext     *context,
+                             GHashTable      *cache,
+                             GList           *writable_path,
+                             GFile           *file,
+                             guint64          mtime,
+                             GFile           *top_directory)
 {
-  GimpDataLoadContext              *context   = data;
-  GimpDataFactory                  *factory   = context->factory;
-  GHashTable                       *cache     = context->cache;
   const GimpDataFactoryLoaderEntry *loader    = NULL;
   GList                            *data_list = NULL;
-  GFile                            *file;
+  gchar                            *uri;
   GInputStream                     *input;
   gint                              i;
   GError                           *error = NULL;
 
+  uri = g_file_get_uri (file);
+
   for (i = 0; i < factory->priv->n_loader_entries; i++)
     {
       loader = &factory->priv->loader_entries[i];
@@ -863,31 +885,30 @@ gimp_data_factory_load_data (const GimpDatafileData *file_data,
        * which must be last in the loader array
        */
       if (! loader->extension ||
-          gimp_datafiles_check_extension (file_data->filename,
-                                          loader->extension))
-        goto insert;
+          gimp_datafiles_check_extension (uri, loader->extension))
+        {
+          goto insert;
+        }
     }
 
+  g_free (uri);
   return;
 
  insert:
-  file = g_file_new_for_path (file_data->filename);
-
   if (cache)
     {
       GList *cached_data = g_hash_table_lookup (cache, file);
 
       if (cached_data &&
           gimp_data_get_mtime (cached_data->data) != 0 &&
-          gimp_data_get_mtime (cached_data->data) == file_data->mtime)
+          gimp_data_get_mtime (cached_data->data) == mtime)
         {
           GList *list;
 
           for (list = cached_data; list; list = g_list_next (list))
             gimp_container_add (factory->priv->container, list->data);
 
-          g_object_unref (file);
-
+          g_free (uri);
           return;
         }
     }
@@ -896,7 +917,7 @@ gimp_data_factory_load_data (const GimpDatafileData *file_data,
 
   if (input)
     {
-      data_list = loader->load_func (context->context, file, input, &error);
+      data_list = loader->load_func (context, file, input, &error);
 
       if (error)
         {
@@ -927,15 +948,14 @@ gimp_data_factory_load_data (const GimpDatafileData *file_data,
       gboolean  writable  = FALSE;
       gboolean  deletable = FALSE;
 
-      obsolete = (strstr (file_data->dirname,
-                          GIMP_OBSOLETE_DATA_DIR_NAME) != 0);
+      obsolete = (strstr (uri, GIMP_OBSOLETE_DATA_DIR_NAME) != 0);
 
       /* obsolete files are immutable, don't check their writability */
       if (! obsolete)
         {
           deletable = (g_list_length (data_list) == 1 &&
-                       gimp_data_factory_is_dir_writable (file_data->dirname,
-                                                          context->writable_path));
+                       gimp_data_factory_is_dir_writable (uri,
+                                                          writable_path));
 
           writable = (deletable && loader->writable);
         }
@@ -945,7 +965,7 @@ gimp_data_factory_load_data (const GimpDatafileData *file_data,
           GimpData *data = list->data;
 
           gimp_data_set_file (data, file, writable, deletable);
-          gimp_data_set_mtime (data, file_data->mtime);
+          gimp_data_set_mtime (data, mtime);
           gimp_data_clean (data);
 
           if (obsolete)
@@ -955,7 +975,7 @@ gimp_data_factory_load_data (const GimpDatafileData *file_data,
             }
           else
             {
-              gimp_data_set_folder_tags (data, context->top_directory);
+              gimp_data_set_folder_tags (data, top_directory);
 
               gimp_container_add (factory->priv->container,
                                   GIMP_OBJECT (data));
@@ -967,7 +987,7 @@ gimp_data_factory_load_data (const GimpDatafileData *file_data,
       g_list_free (data_list);
     }
 
-  g_object_unref (file);
+  g_free (uri);
 
   /*  not else { ... } because loader->load_func() can return a list
    *  of data objects *and* an error message if loading failed after


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