[gnome-software] Allow plugins to create applications with custom GTypes



commit f9173255a3998abcee7b86c252640f5dbce8771d
Author: Richard Hughes <richard hughsie com>
Date:   Thu Jul 13 14:22:40 2017 +0100

    Allow plugins to create applications with custom GTypes
    
    This allows us to stop storing per-app plugin-specific properties as strings in
    the global metadata.

 lib/gs-app.c                |   48 ++++++++++++++++++++++++++-----------
 lib/gs-app.h                |    3 ++
 lib/gs-plugin-loader.c      |    3 +-
 lib/gs-plugin-private.h     |    1 +
 lib/gs-plugin.c             |   55 +++++++++++++++++++++++++++++++++++++++++++
 lib/gs-plugin.h             |    4 +++
 lib/gs-self-test.c          |    4 +-
 plugins/core/gs-appstream.c |    5 ++-
 8 files changed, 104 insertions(+), 19 deletions(-)
---
diff --git a/lib/gs-app.c b/lib/gs-app.c
index 309bfa5..8da3556 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -4009,33 +4009,29 @@ gs_app_new (const gchar *id)
 }
 
 /**
- * gs_app_new_from_unique_id:
+ * gs_app_set_from_unique_id:
+ * @app: a #GsApp
  * @unique_id: an application unique ID, e.g.
  *     `system/flatpak/gnome/desktop/org.gnome.Software.desktop/master`
  *
- * Creates a new application object.
+ * Sets details on an application object.
  *
  * The unique ID will be parsed to set some information in the application such
- * as the scope, bundle kind, id, etc. Unlike gs_app_new(), it cannot take a
- * %NULL argument.
+ * as the scope, bundle kind, id, etc.
  *
- * Returns: a new #GsApp
- *
- * Since: 3.22
+ * Since: 3.26
  **/
-GsApp *
-gs_app_new_from_unique_id (const gchar *unique_id)
+void
+gs_app_set_from_unique_id (GsApp *app, const gchar *unique_id)
 {
-       GsApp *app;
        g_auto(GStrv) split = NULL;
 
-       g_return_val_if_fail (unique_id != NULL, NULL);
+       g_return_if_fail (GS_IS_APP (app));
+       g_return_if_fail (unique_id != NULL);
 
        split = g_strsplit (unique_id, "/", -1);
        if (g_strv_length (split) != 6)
-               return NULL;
-
-       app = gs_app_new (NULL);
+               return;
        if (g_strcmp0 (split[0], "*") != 0)
                gs_app_set_scope (app, as_app_scope_from_string (split[0]));
        if (g_strcmp0 (split[1], "*") != 0)
@@ -4048,6 +4044,30 @@ gs_app_new_from_unique_id (const gchar *unique_id)
                gs_app_set_id (app, split[4]);
        if (g_strcmp0 (split[5], "*") != 0)
                gs_app_set_branch (app, split[5]);
+}
+
+/**
+ * gs_app_new_from_unique_id:
+ * @unique_id: an application unique ID, e.g.
+ *     `system/flatpak/gnome/desktop/org.gnome.Software.desktop/master`
+ *
+ * Creates a new application object.
+ *
+ * The unique ID will be parsed to set some information in the application such
+ * as the scope, bundle kind, id, etc. Unlike gs_app_new(), it cannot take a
+ * %NULL argument.
+ *
+ * Returns: a new #GsApp
+ *
+ * Since: 3.22
+ **/
+GsApp *
+gs_app_new_from_unique_id (const gchar *unique_id)
+{
+       GsApp *app;
+       g_return_val_if_fail (unique_id != NULL, NULL);
+       app = gs_app_new (NULL);
+       gs_app_set_from_unique_id (app, unique_id);
        return app;
 }
 
diff --git a/lib/gs-app.h b/lib/gs-app.h
index d034830..e09bf1a 100644
--- a/lib/gs-app.h
+++ b/lib/gs-app.h
@@ -106,7 +106,10 @@ typedef enum {
 } GsAppQuality;
 
 GsApp          *gs_app_new                     (const gchar    *id);
+G_DEPRECATED_FOR(gs_app_set_from_unique_id)
 GsApp          *gs_app_new_from_unique_id      (const gchar    *unique_id);
+void            gs_app_set_from_unique_id      (GsApp          *app,
+                                                const gchar    *unique_id);
 gchar          *gs_app_to_string               (GsApp          *app);
 
 const gchar    *gs_app_get_id                  (GsApp          *app);
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index e1c2dfa..2e94c1d 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -3581,7 +3581,8 @@ gs_plugin_loader_app_create (GsPluginLoader *plugin_loader, const gchar *unique_
                return g_object_ref (app);
 
        /* create and add */
-       app = gs_app_new_from_unique_id (unique_id);
+       app = gs_app_new (NULL);
+       gs_app_set_from_unique_id (app, unique_id);
        gs_app_list_add (priv->global_cache, app);
        return app;
 }
diff --git a/lib/gs-plugin-private.h b/lib/gs-plugin-private.h
index 7de3a0d..df42f7c 100644
--- a/lib/gs-plugin-private.h
+++ b/lib/gs-plugin-private.h
@@ -71,6 +71,7 @@ GPtrArray     *gs_plugin_get_rules                    (GsPlugin       *plugin,
                                                         GsPluginRule    rule);
 gpointer        gs_plugin_get_symbol                   (GsPlugin       *plugin,
                                                         const gchar    *function_name);
+GType           gs_plugin_get_app_gtype                (GsPlugin       *plugin);
 gchar          *gs_plugin_failure_flags_to_string      (GsPluginFailureFlags failure_flags);
 gchar          *gs_plugin_refine_flags_to_string       (GsPluginRefineFlags refine_flags);
 
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
index 2e2bc57..8a823e5 100644
--- a/lib/gs-plugin.c
+++ b/lib/gs-plugin.c
@@ -74,6 +74,7 @@ typedef struct
        GHashTable              *vfuncs;                /* string:pointer */
        GMutex                   vfuncs_mutex;
        gboolean                 enabled;
+       GType                    app_gtype;
        gchar                   *locale;                /* allow-none */
        gchar                   *language;              /* allow-none */
        gchar                   *name;
@@ -441,6 +442,59 @@ gs_plugin_set_enabled (GsPlugin *plugin, gboolean enabled)
 }
 
 /**
+ * gs_plugin_get_app_gtype:
+ * @plugin: a #GsPlugin
+ *
+ * Gets the native application GType.
+ *
+ * Returns: a #GType, e.g. %GS_TYPE_APP
+ *
+ * Since: 3.26
+ **/
+GType
+gs_plugin_get_app_gtype (GsPlugin *plugin)
+{
+       GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
+       return priv->app_gtype;
+}
+
+/**
+ * gs_plugin_set_app_gtype:
+ * @plugin: a #GsPlugin
+ * @app_gtype: the #GType state
+ *
+ * Sets the native application GType.
+ *
+ * Since: 3.26
+ **/
+void
+gs_plugin_set_app_gtype (GsPlugin *plugin, GType app_gtype)
+{
+       GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
+       priv->app_gtype = app_gtype;
+}
+
+/**
+ * gs_plugin_app_new:
+ * @plugin: a #GsPlugin
+ * @id: an application ID
+ *
+ * Creates a GsApp, which may possibly be a subclassed type.
+ * To set the type used when creating objects, plugins must use
+ * gs_plugin_set_app_gtype() with a custom #GType.
+ *
+ * Returns: a #GsApp
+ *
+ * Since: 3.26
+ **/
+GsApp *
+gs_plugin_app_new (GsPlugin *plugin, const gchar *id)
+{
+       GsPluginPrivate *priv = gs_plugin_get_instance_private (plugin);
+       return GS_APP (g_object_new (priv->app_gtype, "id", id, NULL));
+}
+
+/**
  * gs_plugin_get_name:
  * @plugin: a #GsPlugin
  *
@@ -2155,6 +2209,7 @@ gs_plugin_init (GsPlugin *plugin)
                priv->rules[i] = g_ptr_array_new_with_free_func (g_free);
 
        priv->enabled = TRUE;
+       priv->app_gtype = GS_TYPE_APP;
        priv->scale = 1;
        priv->profile = as_profile_new ();
        priv->cache = g_hash_table_new_full ((GHashFunc) as_utils_unique_id_hash,
diff --git a/lib/gs-plugin.h b/lib/gs-plugin.h
index fe10aa1..822f942 100644
--- a/lib/gs-plugin.h
+++ b/lib/gs-plugin.h
@@ -74,6 +74,10 @@ void          gs_plugin_set_appstream_id             (GsPlugin       *plugin,
 gboolean        gs_plugin_get_enabled                  (GsPlugin       *plugin);
 void            gs_plugin_set_enabled                  (GsPlugin       *plugin,
                                                         gboolean        enabled);
+void            gs_plugin_set_app_gtype                (GsPlugin       *plugin,
+                                                        GType           app_gtype);
+GsApp          *gs_plugin_app_new                      (GsPlugin       *plugin,
+                                                        const gchar    *id);
 gboolean        gs_plugin_has_flags                    (GsPlugin       *plugin,
                                                         GsPluginFlags   flags);
 void            gs_plugin_add_flags                    (GsPlugin       *plugin,
diff --git a/lib/gs-self-test.c b/lib/gs-self-test.c
index 42ebfbe..7cbbb2a 100644
--- a/lib/gs-self-test.c
+++ b/lib/gs-self-test.c
@@ -483,11 +483,11 @@ gs_app_thread_func (void)
 static void
 gs_app_unique_id_func (void)
 {
-       g_autoptr(GsApp) app = NULL;
+       g_autoptr(GsApp) app = gs_app_new (NULL);
        const gchar *unique_id;
 
        unique_id = "system/flatpak/gnome/desktop/org.gnome.Software.desktop/master";
-       app = gs_app_new_from_unique_id (unique_id);
+       gs_app_set_from_unique_id (app, unique_id);
        g_assert (GS_IS_APP (app));
        g_assert_cmpint (gs_app_get_scope (app), ==, AS_APP_SCOPE_SYSTEM);
        g_assert_cmpint (gs_app_get_bundle_kind (app), ==, AS_BUNDLE_KIND_FLATPAK);
diff --git a/plugins/core/gs-appstream.c b/plugins/core/gs-appstream.c
index 5e7b99c..ceb5c63 100644
--- a/plugins/core/gs-appstream.c
+++ b/plugins/core/gs-appstream.c
@@ -47,7 +47,8 @@ gs_appstream_create_app (GsPlugin *plugin, AsApp *item, GError **error)
        }
 
        if (app == NULL) {
-               app = gs_app_new_from_unique_id (unique_id);
+               app = gs_plugin_app_new (plugin, NULL);
+               gs_app_set_from_unique_id (app, unique_id);
                gs_app_set_metadata (app, "GnomeSoftware::Creator",
                                     gs_plugin_get_name (plugin));
                if (!gs_appstream_refine_app (plugin, app, item, error)) {
@@ -333,7 +334,7 @@ gs_appstream_create_runtime (GsPlugin *plugin,
                return NULL;
 
        /* create the complete GsApp from the single string */
-       app = gs_app_new (split[0]);
+       app = gs_plugin_app_new (plugin, split[0]);
        source = g_strdup_printf ("runtime/%s", runtime);
        gs_app_add_source (app, source);
        gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_FLATPAK);


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