[gimp] app: add extension installation in GimpExtensionManager.



commit 50aa7233b27ff711e6176e4f497bff53d07bcb33
Author: Jehan <jehan girinstud io>
Date:   Mon Apr 29 15:47:14 2019 +0900

    app: add extension installation in GimpExtensionManager.
    
    This completes my earlier commit 406279e4ef.
    Extension installation is not about just decompressing a file in the
    right folder. We must also make the extension manager and the GUI aware
    of this newly available extension.

 app/core/gimp-utils.c           | 65 +++++++++++++++++++++++++++
 app/core/gimp-utils.h           |  2 +
 app/core/gimpextensionmanager.c | 97 ++++++++++++++++++-----------------------
 app/core/gimpextensionmanager.h |  6 +++
 app/file-data/file-data-gex.c   | 51 +++++++++++++++++++---
 5 files changed, 160 insertions(+), 61 deletions(-)
---
diff --git a/app/core/gimp-utils.c b/app/core/gimp-utils.c
index ec9d2982c2..24637033ca 100644
--- a/app/core/gimp-utils.c
+++ b/app/core/gimp-utils.c
@@ -905,3 +905,68 @@ gimp_create_image_from_buffer (Gimp        *gimp,
 
   return image;
 }
+
+/**
+ * gimp_rec_rm:
+ * @file: #GFile to delete from file system.
+ * @error:
+ *
+ * Delete @file. If file is a directory, it will delete its children as
+ * well recursively. It will not follow symlinks so you won't end up in
+ * infinite loops, not will you be at risk of deleting your whole file
+ * system (unless you pass the root of course!).
+ * Such function unfortunately does not exist in glib, which only allows
+ * to delete single files or empty directories by default.
+ *
+ * Returns: #TRUE if @file was successfully deleted and all its
+ * children, #FALSE otherwise with @error filled.
+ */
+gboolean
+gimp_rec_rm (GFile   *file,
+             GError **error)
+{
+  gboolean success = TRUE;
+
+  if (g_file_query_exists (file, NULL))
+    {
+      if (g_file_query_file_type (file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                  NULL) == G_FILE_TYPE_DIRECTORY)
+        {
+          GFileEnumerator *enumerator;
+
+          enumerator = g_file_enumerate_children (file,
+                                                  G_FILE_ATTRIBUTE_STANDARD_NAME ","
+                                                  G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
+                                                  G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                                                  G_FILE_QUERY_INFO_NONE,
+                                                  NULL, NULL);
+          if (enumerator)
+            {
+              GFileInfo *info;
+
+              while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
+                {
+                  GFile *child;
+
+                  child = g_file_enumerator_get_child (enumerator, info);
+                  g_object_unref (info);
+
+                  if (! gimp_rec_rm (child, error))
+                    success = FALSE;
+
+                  g_object_unref (child);
+                  if (! success)
+                    break;
+                }
+
+              g_object_unref (enumerator);
+            }
+        }
+
+      if (success)
+        /* Non-directory or empty directory. */
+        success = g_file_delete (file, NULL, error);
+    }
+
+  return success;
+}
diff --git a/app/core/gimp-utils.h b/app/core/gimp-utils.h
index 956216e82b..866936c682 100644
--- a/app/core/gimp-utils.h
+++ b/app/core/gimp-utils.h
@@ -102,5 +102,7 @@ GimpImage  * gimp_create_image_from_buffer         (Gimp            *gimp,
                                                     GeglBuffer      *buffer,
                                                     const gchar     *image_name);
 
+gboolean     gimp_rec_rm                           (GFile                *file,
+                                                    GError              **error);
 
 #endif /* __APP_GIMP_UTILS_H__ */
diff --git a/app/core/gimpextensionmanager.c b/app/core/gimpextensionmanager.c
index 8ea1dec374..bdd8dede31 100644
--- a/app/core/gimpextensionmanager.c
+++ b/app/core/gimpextensionmanager.c
@@ -37,6 +37,7 @@
 #include "gimpextension-error.h"
 #include "gimpobject.h"
 #include "gimpmarshal.h"
+#include "gimp-utils.h"
 
 #include "gimpextensionmanager.h"
 
@@ -61,6 +62,7 @@ enum
 
 enum
 {
+  EXTENSION_INSTALLED,
   EXTENSION_REMOVED,
   LAST_SIGNAL
 };
@@ -124,9 +126,6 @@ static void     gimp_extension_manager_extension_running   (GimpExtension
                                                             GParamSpec           *pspec,
                                                             GimpExtensionManager *manager);
 
-/* Utils. */
-static gboolean gimp_extension_manager_rec_delete          (GFile                *file,
-                                                            GError              **error);
 
 G_DEFINE_TYPE_WITH_CODE (GimpExtensionManager, gimp_extension_manager,
                          GIMP_TYPE_OBJECT,
@@ -194,6 +193,16 @@ gimp_extension_manager_class_init (GimpExtensionManagerClass *klass)
                                                          NULL, NULL,
                                                          GIMP_PARAM_READWRITE));
 
+  signals[EXTENSION_INSTALLED] =
+    g_signal_new ("extension-installed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpExtensionManagerClass, extension_installed),
+                  NULL, NULL,
+                  gimp_marshal_VOID__OBJECT_BOOLEAN,
+                  G_TYPE_NONE, 2,
+                  GIMP_TYPE_EXTENSION,
+                  G_TYPE_BOOLEAN);
   signals[EXTENSION_REMOVED] =
     g_signal_new ("extension-removed",
                   G_TYPE_FROM_CLASS (klass),
@@ -405,7 +414,7 @@ gimp_extension_manager_finalize (GObject *object)
       GFile  *file;
 
       file = g_file_new_for_path (gimp_extension_get_path (iter->data));
-      if (! gimp_extension_manager_rec_delete (file, &error))
+      if (! gimp_rec_rm (file, &error))
         g_warning ("%s: %s\n", G_STRFUNC, error->message);
       g_object_unref (file);
     }
@@ -711,6 +720,36 @@ gimp_extension_manager_can_run (GimpExtensionManager *manager,
   return TRUE;
 }
 
+/**
+ * gimp_extension_manager_install:
+ * @manager:
+ * @extension:
+ * @error:
+ *
+ * Install @extension. This merely adds the extension in the known
+ * extension list to make the manager aware of it at runtime, and to
+ * emit a signal for GUI update.
+ */
+gboolean
+gimp_extension_manager_install (GimpExtensionManager *manager,
+                                GimpExtension        *extension,
+                                GError              **error)
+{
+  gboolean success = FALSE;
+
+  if ((success = gimp_extension_load (extension, error)))
+    {
+      manager->p->extensions = g_list_prepend (manager->p->extensions,
+                                               extension);
+      g_signal_connect (extension, "notify::running",
+                        G_CALLBACK (gimp_extension_manager_extension_running),
+                        manager);
+      g_signal_emit (manager, signals[EXTENSION_INSTALLED], 0, extension, FALSE);
+    }
+
+  return success;
+}
+
 /**
  * gimp_extension_manager_remove:
  * @manager:
@@ -967,53 +1006,3 @@ gimp_extension_manager_extension_running (GimpExtension        *extension,
 
   gimp_extension_manager_refresh (manager);
 }
-
-static gboolean
-gimp_extension_manager_rec_delete (GFile   *file,
-                                   GError **error)
-{
-  gboolean success = TRUE;
-
-  if (g_file_query_exists (file, NULL))
-    {
-      if (g_file_query_file_type (file, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                  NULL) == G_FILE_TYPE_DIRECTORY)
-        {
-          GFileEnumerator *enumerator;
-
-          enumerator = g_file_enumerate_children (file,
-                                                  G_FILE_ATTRIBUTE_STANDARD_NAME ","
-                                                  G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN ","
-                                                  G_FILE_ATTRIBUTE_TIME_MODIFIED,
-                                                  G_FILE_QUERY_INFO_NONE,
-                                                  NULL, NULL);
-          if (enumerator)
-            {
-              GFileInfo *info;
-
-              while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)))
-                {
-                  GFile *child;
-
-                  child = g_file_enumerator_get_child (enumerator, info);
-                  g_object_unref (info);
-
-                  if (! gimp_extension_manager_rec_delete (child, error))
-                    success = FALSE;
-
-                  g_object_unref (child);
-                  if (! success)
-                    break;
-                }
-
-              g_object_unref (enumerator);
-            }
-        }
-
-      if (success)
-        /* Non-directory or empty directory. */
-        success = g_file_delete (file, NULL, error);
-    }
-
-  return success;
-}
diff --git a/app/core/gimpextensionmanager.h b/app/core/gimpextensionmanager.h
index a4bc1edd3d..7aebedeaa0 100644
--- a/app/core/gimpextensionmanager.h
+++ b/app/core/gimpextensionmanager.h
@@ -47,6 +47,9 @@ struct _GimpExtensionManagerClass
 {
   GimpObjectClass      parent_class;
 
+  void              (* extension_installed) (GimpExtensionManager *manager,
+                                             GimpExtension        *extension,
+                                             gboolean              is_system_ext);
   void              (* extension_removed)   (GimpExtensionManager *manager,
                                              gchar                *extension_id);
 };
@@ -67,6 +70,9 @@ gboolean               gimp_extension_manager_is_running            (GimpExtensi
 gboolean               gimp_extension_manager_can_run               (GimpExtensionManager *manager,
                                                                      GimpExtension        *extension);
 
+gboolean               gimp_extension_manager_install               (GimpExtensionManager *manager,
+                                                                     GimpExtension        *extension,
+                                                                     GError              **error);
 gboolean               gimp_extension_manager_remove                (GimpExtensionManager *manager,
                                                                      GimpExtension        *extension,
                                                                      GError              **error);
diff --git a/app/file-data/file-data-gex.c b/app/file-data/file-data-gex.c
index c10850d34c..efccb5d496 100644
--- a/app/file-data/file-data-gex.c
+++ b/app/file-data/file-data-gex.c
@@ -37,11 +37,14 @@
 #include "core/gimpbrush-load.h"
 #include "core/gimpbrush-private.h"
 #include "core/gimpdrawable.h"
+#include "core/gimpextension.h"
+#include "core/gimpextensionmanager.h"
 #include "core/gimpextension-error.h"
 #include "core/gimpimage.h"
 #include "core/gimplayer-new.h"
 #include "core/gimpparamspecs.h"
 #include "core/gimptempbuf.h"
+#include "core/gimp-utils.h"
 
 #include "pdb/gimpprocedure.h"
 
@@ -75,7 +78,7 @@ static gboolean   file_gex_validate_path  (const gchar     *path,
 static gboolean   file_gex_validate       (GFile           *file,
                                            AsApp          **appstream,
                                            GError         **error);
-static gboolean   file_gex_decompress     (GFile           *file,
+static gchar *    file_gex_decompress     (GFile           *file,
                                            gchar           *plugin_id,
                                            GError         **error);
 
@@ -342,13 +345,14 @@ file_gex_validate (GFile   *file,
   return success;
 }
 
-static gboolean
+static gchar *
 file_gex_decompress (GFile   *file,
                      gchar   *plugin_id,
                      GError **error)
 {
   GInputStream *input;
   GFile        *ext_dir = gimp_directory_file ("extensions", NULL);
+  gchar        *plugin_dir = NULL;
   gboolean      success = FALSE;
 
   g_return_val_if_fail (error != NULL && *error == NULL, FALSE);
@@ -476,9 +480,12 @@ file_gex_decompress (GFile   *file,
                       gimp_file_get_utf8_name (file));
     }
 
+  if (success)
+    plugin_dir = g_build_filename (g_file_get_path (ext_dir), plugin_id, NULL);
+
   g_object_unref (ext_dir);
 
-  return success;
+  return plugin_dir;
 }
 
 /*  public functions  */
@@ -494,16 +501,46 @@ file_gex_load_invoker (GimpProcedure         *procedure,
   GimpValueArray *return_vals;
   const gchar    *uri;
   GFile          *file;
-  gboolean        success   = FALSE;
-  AsApp          *appdata   = NULL;
+  gchar          *ext_dir = NULL;
+  AsApp          *appdata = NULL;
+  gboolean        success = FALSE;
 
   gimp_set_busy (gimp);
 
   uri  = g_value_get_string (gimp_value_array_index (args, 1));
   file = g_file_new_for_uri (uri);
 
-  if (file_gex_validate (file, &appdata, error))
-    success = file_gex_decompress (file, (gchar *) as_app_get_id (appdata), error);
+  success = file_gex_validate (file, &appdata, error);
+  if (success)
+    ext_dir = file_gex_decompress (file, (gchar *) as_app_get_id (appdata), error);
+  if (ext_dir)
+    {
+      GimpExtension *extension;
+      GError        *rm_error = NULL;
+
+      extension = gimp_extension_new (ext_dir, TRUE);
+      success   = gimp_extension_manager_install (gimp->extension_manager, extension, error);
+
+      if (! success)
+        {
+          GFile *file;
+
+          g_object_unref (extension);
+
+          file = g_file_new_for_path (ext_dir);
+          if (! gimp_rec_rm (file, &rm_error))
+            {
+              g_warning ("%s: %s\n", G_STRFUNC, rm_error->message);
+              g_error_free (rm_error);
+            }
+          g_object_unref (file);
+        }
+      g_free (ext_dir);
+    }
+  else
+    {
+      success = FALSE;
+    }
 
   g_object_unref (file);
 


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