[gnome-builder] libide/foundry: add SDK abstraction for installations



commit 7b4c11c321d1336d55778a13501e9a6e30e5ded3
Author: Christian Hergert <chergert redhat com>
Date:   Mon Aug 22 17:59:23 2022 -0700

    libide/foundry: add SDK abstraction for installations
    
    The goal is for this to be a simplified interface for installing SDKs
    from the preferences without having to do surgery to the IdeRuntime system.
    
    It can be separate from anything IdeObject/IdeContext related.

 src/libide/foundry/ide-foundry-types.h |   3 +
 src/libide/foundry/ide-sdk-manager.c   | 247 +++++++++++++++++++++++++++++++++
 src/libide/foundry/ide-sdk-manager.h   |  37 +++++
 src/libide/foundry/ide-sdk-private.h   |  30 ++++
 src/libide/foundry/ide-sdk-provider.c  | 231 ++++++++++++++++++++++++++++++
 src/libide/foundry/ide-sdk-provider.h  |  75 ++++++++++
 src/libide/foundry/ide-sdk.c           | 161 +++++++++++++++++++++
 src/libide/foundry/ide-sdk.h           |  66 +++++++++
 src/libide/foundry/libide-foundry.h    |   3 +
 src/libide/foundry/meson.build         |   6 +
 10 files changed, 859 insertions(+)
---
diff --git a/src/libide/foundry/ide-foundry-types.h b/src/libide/foundry/ide-foundry-types.h
index 77c31e874..397348c69 100644
--- a/src/libide/foundry/ide-foundry-types.h
+++ b/src/libide/foundry/ide-foundry-types.h
@@ -58,6 +58,9 @@ typedef struct _IdeRunManager IdeRunManager;
 typedef struct _IdeRuntime IdeRuntime;
 typedef struct _IdeRuntimeManager IdeRuntimeManager;
 typedef struct _IdeRuntimeProvider IdeRuntimeProvider;
+typedef struct _IdeSdk IdeSdk;
+typedef struct _IdeSdkProvider IdeSdkProvider;
+typedef struct _IdeSdkManager IdeSdkManager;
 typedef struct _IdeSimpleBuildTarget IdeSimpleBuildTarget;
 typedef struct _IdeSimpleToolchain IdeSimpleToolchain;
 typedef struct _IdeTest IdeTest;
diff --git a/src/libide/foundry/ide-sdk-manager.c b/src/libide/foundry/ide-sdk-manager.c
new file mode 100644
index 000000000..2505d64d3
--- /dev/null
+++ b/src/libide/foundry/ide-sdk-manager.c
@@ -0,0 +1,247 @@
+/* ide-sdk-manager.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-sdk-manager"
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+
+#include "ide-sdk.h"
+#include "ide-sdk-manager.h"
+#include "ide-sdk-provider.h"
+
+struct _IdeSdkManager
+{
+  GObject              parent_instance;
+  GListStore          *providers;
+  GtkFlattenListModel *sdks;
+  PeasExtensionSet    *addins;
+};
+
+static GType
+ide_sdk_manager_get_item_type (GListModel *model)
+{
+  return IDE_TYPE_SDK;
+}
+
+static guint
+ide_sdk_manager_get_n_items (GListModel *model)
+{
+  IdeSdkManager *self = IDE_SDK_MANAGER (model);
+
+  return self->sdks ? g_list_model_get_n_items (G_LIST_MODEL (self->sdks)) : 0;
+}
+
+static gpointer
+ide_sdk_manager_get_item (GListModel *model,
+                          guint       position)
+{
+  IdeSdkManager *self = IDE_SDK_MANAGER (model);
+
+  return self->sdks ? g_list_model_get_item (G_LIST_MODEL (self->sdks), position) : NULL;
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+  iface->get_item_type = ide_sdk_manager_get_item_type;
+  iface->get_n_items = ide_sdk_manager_get_n_items;
+  iface->get_item = ide_sdk_manager_get_item;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (IdeSdkManager, ide_sdk_manager, G_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+enum {
+  PROP_0,
+  PROP_N_ITEMS,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_sdk_manager_extension_added_cb (PeasExtensionSet *set,
+                                    PeasPluginInfo   *plugin_info,
+                                    PeasExtension    *exten,
+                                    gpointer          user_data)
+{
+  IdeSdkProvider *provider = (IdeSdkProvider *)exten;
+  IdeSdkManager *self = user_data;
+
+  g_assert (PEAS_IS_EXTENSION_SET (set));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_SDK_PROVIDER (provider));
+  g_assert (IDE_IS_SDK_MANAGER (self));
+
+  g_list_store_append (self->providers, provider);
+}
+
+static void
+ide_sdk_manager_extension_removed_cb (PeasExtensionSet *set,
+                                      PeasPluginInfo   *plugin_info,
+                                      PeasExtension    *exten,
+                                      gpointer          user_data)
+{
+  IdeSdkProvider *provider = (IdeSdkProvider *)exten;
+  IdeSdkManager *self = user_data;
+  guint n_items;
+
+  g_assert (PEAS_IS_EXTENSION_SET (set));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_SDK_PROVIDER (provider));
+  g_assert (IDE_IS_SDK_MANAGER (self));
+
+  n_items = g_list_model_get_n_items (G_LIST_MODEL (self->providers));
+
+  for (guint i = 0; i < n_items; i++)
+    {
+      g_autoptr(IdeSdkProvider) element = g_list_model_get_item (G_LIST_MODEL (self->providers), i);
+
+      if (element == provider)
+        {
+          g_list_store_remove (self->providers, i);
+          break;
+        }
+    }
+}
+
+static void
+ide_sdk_manager_items_changed_cb (IdeSdkManager *self,
+                                  guint          position,
+                                  guint          removed,
+                                  guint          added,
+                                  GListModel    *model)
+{
+  g_assert (IDE_IS_SDK_MANAGER (self));
+  g_assert (G_IS_LIST_MODEL (model));
+
+  g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
+
+  if (removed != added)
+    g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_N_ITEMS]);
+}
+
+static void
+ide_sdk_manager_constructed (GObject *object)
+{
+  IdeSdkManager *self = (IdeSdkManager *)object;
+
+  G_OBJECT_CLASS (ide_sdk_manager_parent_class)->constructed (object);
+
+  self->addins = peas_extension_set_new (peas_engine_get_default (),
+                                         IDE_TYPE_SDK_PROVIDER,
+                                         NULL);
+  g_signal_connect (self->addins,
+                    "extension-added",
+                    G_CALLBACK (ide_sdk_manager_extension_added_cb),
+                    self);
+  g_signal_connect (self->addins,
+                    "extension-removed",
+                    G_CALLBACK (ide_sdk_manager_extension_removed_cb),
+                    self);
+  peas_extension_set_foreach (self->addins,
+                              ide_sdk_manager_extension_added_cb,
+                              self);
+}
+
+static void
+ide_sdk_manager_dispose (GObject *object)
+{
+  IdeSdkManager *self = (IdeSdkManager *)object;
+
+  g_clear_object (&self->sdks);
+  g_clear_object (&self->addins);
+  g_clear_object (&self->providers);
+
+  G_OBJECT_CLASS (ide_sdk_manager_parent_class)->dispose (object);
+}
+
+static void
+ide_sdk_manager_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+  IdeSdkManager *self = IDE_SDK_MANAGER (object);
+
+  switch (prop_id)
+    {
+    case PROP_N_ITEMS:
+      g_value_set_uint (value, g_list_model_get_n_items (G_LIST_MODEL (self)));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_sdk_manager_class_init (IdeSdkManagerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = ide_sdk_manager_constructed;
+  object_class->dispose = ide_sdk_manager_dispose;
+  object_class->get_property = ide_sdk_manager_get_property;
+
+  properties [PROP_N_ITEMS] =
+    g_param_spec_uint ("n-items", NULL, NULL, 0, G_MAXUINT, 0,
+                       (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_sdk_manager_init (IdeSdkManager *self)
+{
+  self->providers = g_list_store_new (G_TYPE_LIST_MODEL);
+  self->sdks = gtk_flatten_list_model_new (g_object_ref (G_LIST_MODEL (self->providers)));
+
+  g_signal_connect_object (self->sdks,
+                           "items-changed",
+                           G_CALLBACK (ide_sdk_manager_items_changed_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+/**
+ * ide_sdk_manager_get_default:
+ *
+ * Gets the #IdeSdkManager instance.
+ *
+ * Returns: (transfer none): an #IdeSdkManager
+ */
+IdeSdkManager *
+ide_sdk_manager_get_default (void)
+{
+  static IdeSdkManager *instance;
+
+  if (g_once_init_enter (&instance))
+    {
+      IdeSdkManager *self = g_object_new (IDE_TYPE_SDK_MANAGER, NULL);
+      g_object_add_weak_pointer (G_OBJECT (self), (gpointer *)&instance);
+      g_once_init_leave (&instance, self);
+    }
+
+  return instance;
+}
diff --git a/src/libide/foundry/ide-sdk-manager.h b/src/libide/foundry/ide-sdk-manager.h
new file mode 100644
index 000000000..4fa716e0f
--- /dev/null
+++ b/src/libide/foundry/ide-sdk-manager.h
@@ -0,0 +1,37 @@
+/* ide-sdk-manager.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#if !defined (IDE_FOUNDRY_INSIDE) && !defined (IDE_FOUNDRY_COMPILATION)
+# error "Only <libide-foundry.h> can be included directly."
+#endif
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SDK_MANAGER (ide_sdk_manager_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (IdeSdkManager, ide_sdk_manager, IDE, SDK_MANAGER, GObject)
+
+IDE_AVAILABLE_IN_ALL
+IdeSdkManager *ide_sdk_manager_get_default (void);
+
+G_END_DECLS
diff --git a/src/libide/foundry/ide-sdk-private.h b/src/libide/foundry/ide-sdk-private.h
new file mode 100644
index 000000000..cd1ded72e
--- /dev/null
+++ b/src/libide/foundry/ide-sdk-private.h
@@ -0,0 +1,30 @@
+/* ide-sdk-private.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include "ide-sdk.h"
+
+G_BEGIN_DECLS
+
+void _ide_sdk_set_provider (IdeSdk         *self,
+                            IdeSdkProvider *provider);
+
+G_END_DECLS
diff --git a/src/libide/foundry/ide-sdk-provider.c b/src/libide/foundry/ide-sdk-provider.c
new file mode 100644
index 000000000..46cf170da
--- /dev/null
+++ b/src/libide/foundry/ide-sdk-provider.c
@@ -0,0 +1,231 @@
+/* ide-sdk-provider.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-sdk-provider"
+
+#include "config.h"
+
+#include "ide-sdk-private.h"
+#include "ide-sdk-provider.h"
+
+typedef struct
+{
+  GPtrArray *sdks;
+} IdeSdkProviderPrivate;
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (IdeSdkProvider, ide_sdk_provider, G_TYPE_OBJECT,
+                                  G_ADD_PRIVATE (IdeSdkProvider)
+                                  G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+enum {
+  SDK_ADDED,
+  SDK_REMOVED,
+  N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
+
+static void
+ide_sdk_provider_real_sdk_added (IdeSdkProvider *self,
+                                 IdeSdk         *sdk)
+{
+  IdeSdkProviderPrivate *priv = ide_sdk_provider_get_instance_private (self);
+  guint position;
+
+  g_assert (IDE_IS_SDK_PROVIDER (self));
+  g_assert (IDE_IS_SDK (sdk));
+
+  _ide_sdk_set_provider (sdk, self);
+
+  position = priv->sdks->len;
+  g_ptr_array_add (priv->sdks, g_object_ref (sdk));
+  g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
+}
+
+static void
+ide_sdk_provider_real_sdk_removed (IdeSdkProvider *self,
+                                   IdeSdk         *sdk)
+{
+  IdeSdkProviderPrivate *priv = ide_sdk_provider_get_instance_private (self);
+  guint position;
+
+  g_assert (IDE_IS_SDK_PROVIDER (self));
+  g_assert (IDE_IS_SDK (sdk));
+
+  if (g_ptr_array_find (priv->sdks, sdk, &position))
+    {
+      g_ptr_array_remove_index (priv->sdks, position);
+      g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
+    }
+}
+
+static void
+ide_sdk_provider_dispose (GObject *object)
+{
+  IdeSdkProvider *self = (IdeSdkProvider *)object;
+  IdeSdkProviderPrivate *priv = ide_sdk_provider_get_instance_private (self);
+
+  g_clear_pointer (&priv->sdks, g_ptr_array_unref);
+
+  G_OBJECT_CLASS (ide_sdk_provider_parent_class)->dispose (object);
+}
+
+static void
+ide_sdk_provider_class_init (IdeSdkProviderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = ide_sdk_provider_dispose;
+
+  klass->sdk_added = ide_sdk_provider_real_sdk_added;
+  klass->sdk_removed = ide_sdk_provider_real_sdk_removed;
+
+  signals [SDK_ADDED] =
+    g_signal_new ("sdk-added",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (IdeSdkProviderClass, sdk_added),
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE, 1, IDE_TYPE_SDK);
+
+  signals [SDK_REMOVED] =
+    g_signal_new ("sdk-removed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (IdeSdkProviderClass, sdk_removed),
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE, 1, IDE_TYPE_SDK);
+}
+
+static void
+ide_sdk_provider_init (IdeSdkProvider *self)
+{
+  IdeSdkProviderPrivate *priv = ide_sdk_provider_get_instance_private (self);
+
+  priv->sdks = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+void
+ide_sdk_provider_sdk_added (IdeSdkProvider *self,
+                            IdeSdk         *sdk)
+{
+  g_return_if_fail (IDE_IS_SDK_PROVIDER (self));
+  g_return_if_fail (IDE_IS_SDK (sdk));
+
+  g_signal_emit (self, signals [SDK_ADDED], 0, sdk);
+}
+
+void
+ide_sdk_provider_sdk_removed (IdeSdkProvider *self,
+                              IdeSdk         *sdk)
+{
+  g_return_if_fail (IDE_IS_SDK_PROVIDER (self));
+  g_return_if_fail (IDE_IS_SDK (sdk));
+
+  g_signal_emit (self, signals [SDK_REMOVED], 0, sdk);
+}
+
+/**
+ * ide_sdk_provider_update_async:
+ * @self: a #IdeSdkProvider
+ * @sdk: an #IdeSdk
+ * @notif: (nullable): an #IdeNotification
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @callback: callback to execute upon completion
+ * @user_data: user data for @callback
+ *
+ * Asynchronous request to update an #IdeSdk from the provider.
+ */
+void
+ide_sdk_provider_update_async (IdeSdkProvider      *self,
+                               IdeSdk              *sdk,
+                               IdeNotification     *notif,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
+{
+  g_return_if_fail (IDE_IS_SDK_PROVIDER (self));
+  g_return_if_fail (IDE_IS_SDK (sdk));
+  g_return_if_fail (!notif || IDE_IS_NOTIFICATION (notif));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  IDE_SDK_PROVIDER_GET_CLASS (self)->update_async (self, sdk, notif, cancellable, callback, user_data);
+}
+
+/**
+ * ide_sdk_provider_update_finish:
+ * @self: a #IdeSdkProvider
+ * @result: a #GAsyncResult
+ * @error: a location for a #GError
+ *
+ * Gets result of ide_sdk_provider_update_async().
+ *
+ * Returns: %TRUE if successful; otherwise %FALSE and @error is set.
+ */
+gboolean
+ide_sdk_provider_update_finish (IdeSdkProvider  *self,
+                                GAsyncResult    *result,
+                                GError         **error)
+{
+  g_return_val_if_fail (IDE_IS_SDK_PROVIDER (self), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  return IDE_SDK_PROVIDER_GET_CLASS (self)->update_finish (self, result, error);
+}
+
+static GType
+ide_sdk_provider_get_item_type (GListModel *model)
+{
+  return IDE_TYPE_SDK;
+}
+
+static guint
+ide_sdk_provider_get_n_items (GListModel *model)
+{
+  IdeSdkProvider *self = IDE_SDK_PROVIDER (model);
+  IdeSdkProviderPrivate *priv = ide_sdk_provider_get_instance_private (self);
+
+  return priv->sdks ? priv->sdks->len : 0;
+}
+
+static gpointer
+ide_sdk_provider_get_item (GListModel *model,
+                           guint       position)
+{
+  IdeSdkProvider *self = IDE_SDK_PROVIDER (model);
+  IdeSdkProviderPrivate *priv = ide_sdk_provider_get_instance_private (self);
+
+  if (priv->sdks == NULL || priv->sdks->len <= position)
+    return NULL;
+
+  return g_object_ref (g_ptr_array_index (priv->sdks, position));
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+  iface->get_item_type = ide_sdk_provider_get_item_type;
+  iface->get_n_items = ide_sdk_provider_get_n_items;
+  iface->get_item = ide_sdk_provider_get_item;
+}
diff --git a/src/libide/foundry/ide-sdk-provider.h b/src/libide/foundry/ide-sdk-provider.h
new file mode 100644
index 000000000..013ec594d
--- /dev/null
+++ b/src/libide/foundry/ide-sdk-provider.h
@@ -0,0 +1,75 @@
+/* ide-sdk-provider.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#if !defined (IDE_FOUNDRY_INSIDE) && !defined (IDE_FOUNDRY_COMPILATION)
+# error "Only <libide-foundry.h> can be included directly."
+#endif
+
+#include <libide-core.h>
+
+#include "ide-sdk.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SDK_PROVIDER (ide_sdk_provider_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_DERIVABLE_TYPE (IdeSdkProvider, ide_sdk_provider, IDE, SDK_PROVIDER, GObject)
+
+struct _IdeSdkProviderClass
+{
+  GObjectClass parent_class;
+
+  void        (*sdk_added)     (IdeSdkProvider       *self,
+                                IdeSdk               *sdk);
+  void        (*sdk_removed)   (IdeSdkProvider       *self,
+                                IdeSdk               *sdk);
+  void        (*update_async)  (IdeSdkProvider       *self,
+                                IdeSdk               *sdk,
+                                IdeNotification      *notif,
+                                GCancellable         *cancellable,
+                                GAsyncReadyCallback   callback,
+                                gpointer              user_data);
+  gboolean    (*update_finish) (IdeSdkProvider       *self,
+                                GAsyncResult         *result,
+                                GError              **error);
+};
+
+IDE_AVAILABLE_IN_ALL
+void        ide_sdk_provider_sdk_added     (IdeSdkProvider       *self,
+                                            IdeSdk               *sdk);
+IDE_AVAILABLE_IN_ALL
+void        ide_sdk_provider_sdk_removed   (IdeSdkProvider       *self,
+                                            IdeSdk               *sdk);
+IDE_AVAILABLE_IN_ALL
+void        ide_sdk_provider_update_async  (IdeSdkProvider       *self,
+                                            IdeSdk               *sdk,
+                                            IdeNotification      *notif,
+                                            GCancellable         *cancellable,
+                                            GAsyncReadyCallback   callback,
+                                            gpointer              user_data);
+IDE_AVAILABLE_IN_ALL
+gboolean    ide_sdk_provider_update_finish (IdeSdkProvider       *self,
+                                            GAsyncResult         *result,
+                                            GError              **error);
+
+G_END_DECLS
diff --git a/src/libide/foundry/ide-sdk.c b/src/libide/foundry/ide-sdk.c
new file mode 100644
index 000000000..0165e2f78
--- /dev/null
+++ b/src/libide/foundry/ide-sdk.c
@@ -0,0 +1,161 @@
+/* ide-sdk.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-sdk"
+
+#include "config.h"
+
+#include "ide-sdk-private.h"
+#include "ide-sdk-provider.h"
+
+typedef struct
+{
+  IdeSdkProvider *provider;
+  char *title;
+  char *subtitle;
+  guint can_update : 1;
+  guint installed : 1;
+} IdeSdkPrivate;
+
+enum {
+  PROP_0,
+  PROP_CAN_UPDATE,
+  PROP_INSTALLED,
+  PROP_SUBTITLE,
+  PROP_TITLE,
+  N_PROPS
+};
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (IdeSdk, ide_sdk, G_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_sdk_dispose (GObject *object)
+{
+  IdeSdk *self = (IdeSdk *)object;
+  IdeSdkPrivate *priv = ide_sdk_get_instance_private (self);
+
+  g_clear_weak_pointer (&priv->provider);
+  g_clear_pointer (&priv->subtitle, g_free);
+  g_clear_pointer (&priv->title, g_free);
+
+  G_OBJECT_CLASS (ide_sdk_parent_class)->dispose (object);
+}
+
+static void
+ide_sdk_get_property (GObject    *object,
+                      guint       prop_id,
+                      GValue     *value,
+                      GParamSpec *pspec)
+{
+  IdeSdk *self = IDE_SDK (object);
+
+  switch (prop_id)
+    {
+    IDE_GET_PROPERTY_BOOLEAN (ide_sdk, can_update, CAN_UPDATE);
+    IDE_GET_PROPERTY_BOOLEAN (ide_sdk, installed, INSTALLED);
+    IDE_GET_PROPERTY_STRING (ide_sdk, subtitle, SUBTITLE);
+    IDE_GET_PROPERTY_STRING (ide_sdk, title, TITLE);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_sdk_set_property (GObject      *object,
+                      guint         prop_id,
+                      const GValue *value,
+                      GParamSpec   *pspec)
+{
+  IdeSdk *self = IDE_SDK (object);
+
+  switch (prop_id)
+    {
+    IDE_SET_PROPERTY_BOOLEAN (ide_sdk, can_update, CAN_UPDATE);
+    IDE_SET_PROPERTY_BOOLEAN (ide_sdk, installed, INSTALLED);
+    IDE_SET_PROPERTY_STRING (ide_sdk, subtitle, SUBTITLE);
+    IDE_SET_PROPERTY_STRING (ide_sdk, title, TITLE);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_sdk_class_init (IdeSdkClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = ide_sdk_dispose;
+  object_class->get_property = ide_sdk_get_property;
+  object_class->set_property = ide_sdk_set_property;
+
+  IDE_DEFINE_BOOLEAN_PROPERTY ("can-update", FALSE, G_PARAM_READWRITE, CAN_UPDATE)
+  IDE_DEFINE_BOOLEAN_PROPERTY ("installed", FALSE, G_PARAM_READWRITE, INSTALLED)
+  IDE_DEFINE_STRING_PROPERTY ("subtitle", NULL, G_PARAM_READWRITE, SUBTITLE)
+  IDE_DEFINE_STRING_PROPERTY ("title", NULL, G_PARAM_READWRITE, TITLE)
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_sdk_init (IdeSdk *self)
+{
+}
+
+IDE_DEFINE_BOOLEAN_GETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, can_update)
+IDE_DEFINE_BOOLEAN_GETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, installed)
+IDE_DEFINE_STRING_GETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, subtitle)
+IDE_DEFINE_STRING_GETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, title)
+
+IDE_DEFINE_BOOLEAN_SETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, can_update, CAN_UPDATE)
+IDE_DEFINE_BOOLEAN_SETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, installed, INSTALLED)
+IDE_DEFINE_STRING_SETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, subtitle, SUBTITLE)
+IDE_DEFINE_STRING_SETTER_PRIVATE (ide_sdk, IdeSdk, IDE_TYPE_SDK, title, TITLE)
+
+void
+_ide_sdk_set_provider (IdeSdk         *self,
+                       IdeSdkProvider *provider)
+{
+  IdeSdkPrivate *priv = ide_sdk_get_instance_private (self);
+
+  g_return_if_fail (IDE_IS_SDK (self));
+  g_return_if_fail (!provider || IDE_IS_SDK_PROVIDER (provider));
+
+  g_set_weak_pointer (&priv->provider, provider);
+}
+
+/**
+ * ide_sdk_get_provider:
+ * @self: a #IdeSdk
+ *
+ * Gets the provider of the SDK.
+ *
+ * Returns: (transfer none): an #IdeSdkProvider
+ */
+IdeSdkProvider *
+ide_sdk_get_provider (IdeSdk *self)
+{
+  IdeSdkPrivate *priv = ide_sdk_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_SDK (self), NULL);
+
+  return priv->provider;
+}
diff --git a/src/libide/foundry/ide-sdk.h b/src/libide/foundry/ide-sdk.h
new file mode 100644
index 000000000..388023dc2
--- /dev/null
+++ b/src/libide/foundry/ide-sdk.h
@@ -0,0 +1,66 @@
+/* ide-sdk.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#if !defined (IDE_FOUNDRY_INSIDE) && !defined (IDE_FOUNDRY_COMPILATION)
+# error "Only <libide-foundry.h> can be included directly."
+#endif
+
+#include <libide-core.h>
+
+#include "ide-foundry-types.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SDK (ide_sdk_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_DERIVABLE_TYPE (IdeSdk, ide_sdk, IDE, SDK, GObject)
+
+struct _IdeSdkClass
+{
+  GObjectClass parent_class;
+};
+
+IDE_AVAILABLE_IN_ALL
+IdeSdkProvider *ide_sdk_get_provider   (IdeSdk     *self);
+IDE_AVAILABLE_IN_ALL
+gboolean        ide_sdk_get_can_update (IdeSdk     *self);
+IDE_AVAILABLE_IN_ALL
+void            ide_sdk_set_can_update (IdeSdk     *self,
+                                        gboolean    can_update);
+IDE_AVAILABLE_IN_ALL
+gboolean        ide_sdk_get_installed  (IdeSdk     *self);
+IDE_AVAILABLE_IN_ALL
+void            ide_sdk_set_installed  (IdeSdk     *self,
+                                        gboolean    installed);
+IDE_AVAILABLE_IN_ALL
+const char     *ide_sdk_get_title      (IdeSdk     *self);
+IDE_AVAILABLE_IN_ALL
+void            ide_sdk_set_title      (IdeSdk     *self,
+                                        const char *title);
+IDE_AVAILABLE_IN_ALL
+const char     *ide_sdk_get_subtitle   (IdeSdk     *self);
+IDE_AVAILABLE_IN_ALL
+void            ide_sdk_set_subtitle   (IdeSdk     *self,
+                                        const char *subtitle);
+
+G_END_DECLS
diff --git a/src/libide/foundry/libide-foundry.h b/src/libide/foundry/libide-foundry.h
index a0a76a150..e2c14fea3 100644
--- a/src/libide/foundry/libide-foundry.h
+++ b/src/libide/foundry/libide-foundry.h
@@ -66,6 +66,9 @@ G_BEGIN_DECLS
 #include "ide-runtime-manager.h"
 #include "ide-runtime-provider.h"
 #include "ide-runtime.h"
+#include "ide-sdk.h"
+#include "ide-sdk-manager.h"
+#include "ide-sdk-provider.h"
 #include "ide-simple-build-system-discovery.h"
 #include "ide-simple-build-target.h"
 #include "ide-simple-toolchain.h"
diff --git a/src/libide/foundry/meson.build b/src/libide/foundry/meson.build
index 2198cb241..7c22c396d 100644
--- a/src/libide/foundry/meson.build
+++ b/src/libide/foundry/meson.build
@@ -51,6 +51,9 @@ libide_foundry_public_headers = [
   'ide-runtime-manager.h',
   'ide-runtime-provider.h',
   'ide-runtime.h',
+  'ide-sdk.h',
+  'ide-sdk-manager.h',
+  'ide-sdk-provider.h',
   'ide-simple-build-system-discovery.h',
   'ide-simple-build-target.h',
   'ide-simple-toolchain.h',
@@ -133,6 +136,9 @@ libide_foundry_public_sources = [
   'ide-runtime-manager.c',
   'ide-runtime-provider.c',
   'ide-runtime.c',
+  'ide-sdk.c',
+  'ide-sdk-manager.c',
+  'ide-sdk-provider.c',
   'ide-simple-build-system-discovery.c',
   'ide-simple-build-target.c',
   'ide-simple-toolchain.c',


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