[gnome-builder] libide/plugins: add listmodels for plugin access



commit 757b16fea763628668904330f0c6cc07c7016f35
Author: Christian Hergert <chergert redhat com>
Date:   Wed Aug 17 18:01:34 2022 -0700

    libide/plugins: add listmodels for plugin access

 src/libide/plugins/ide-plugin-private.h         |  29 ++++
 src/libide/plugins/ide-plugin-section-private.h |  29 ++++
 src/libide/plugins/ide-plugin-section.c         | 202 ++++++++++++++++++++++++
 src/libide/plugins/ide-plugin-section.h         |  43 +++++
 src/libide/plugins/ide-plugin.c                 | 182 ++++++++++++++++++++-
 src/libide/plugins/ide-plugin.h                 |  10 +-
 src/libide/plugins/libide-plugins.h             |   1 +
 src/libide/plugins/meson.build                  |   4 +
 8 files changed, 497 insertions(+), 3 deletions(-)
---
diff --git a/src/libide/plugins/ide-plugin-private.h b/src/libide/plugins/ide-plugin-private.h
new file mode 100644
index 000000000..a1f96aa03
--- /dev/null
+++ b/src/libide/plugins/ide-plugin-private.h
@@ -0,0 +1,29 @@
+/* ide-plugin-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 <gio/gio.h>
+
+G_BEGIN_DECLS
+
+GListModel *_ide_plugin_get_all (void);
+
+G_END_DECLS
diff --git a/src/libide/plugins/ide-plugin-section-private.h b/src/libide/plugins/ide-plugin-section-private.h
new file mode 100644
index 000000000..9f93271a8
--- /dev/null
+++ b/src/libide/plugins/ide-plugin-section-private.h
@@ -0,0 +1,29 @@
+/* ide-plugin-section-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 <gio/gio.h>
+
+G_BEGIN_DECLS
+
+GListModel *_ide_plugin_section_get_all (void);
+
+G_END_DECLS
diff --git a/src/libide/plugins/ide-plugin-section.c b/src/libide/plugins/ide-plugin-section.c
new file mode 100644
index 000000000..b4a207822
--- /dev/null
+++ b/src/libide/plugins/ide-plugin-section.c
@@ -0,0 +1,202 @@
+/* ide-plugin-section.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-plugin-section"
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "ide-plugin.h"
+#include "ide-plugin-private.h"
+#include "ide-plugin-section.h"
+#include "ide-plugin-section-private.h"
+
+struct _IdePluginSection
+{
+  GObject     parent_instance;
+  const char *id;
+  GListModel *plugins;
+};
+
+enum {
+  PROP_0,
+  PROP_ID,
+  PROP_PLUGINS,
+  N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (IdePluginSection, ide_plugin_section, G_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_plugin_section_dispose (GObject *object)
+{
+  IdePluginSection *self = (IdePluginSection *)object;
+
+  g_clear_object (&self->plugins);
+
+  G_OBJECT_CLASS (ide_plugin_section_parent_class)->dispose (object);
+}
+
+static void
+ide_plugin_section_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  IdePluginSection *self = IDE_PLUGIN_SECTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_ID:
+      g_value_set_static_string (value, self->id);
+      break;
+
+    case PROP_PLUGINS:
+      g_value_set_object (value, self->plugins);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_plugin_section_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  IdePluginSection *self = IDE_PLUGIN_SECTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_ID:
+      self->id = g_intern_string (g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_plugin_section_class_init (IdePluginSectionClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = ide_plugin_section_dispose;
+  object_class->get_property = ide_plugin_section_get_property;
+  object_class->set_property = ide_plugin_section_set_property;
+
+  properties [PROP_ID] =
+    g_param_spec_string ("id", NULL, NULL, NULL,
+                         (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_PLUGINS] =
+    g_param_spec_object ("plugins", NULL, NULL,
+                         G_TYPE_LIST_MODEL,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_plugin_section_init (IdePluginSection *self)
+{
+}
+
+const char *
+ide_plugin_section_get_id (IdePluginSection *self)
+{
+  g_return_val_if_fail (IDE_IS_PLUGIN_SECTION (self), NULL);
+
+  return self->id;
+}
+
+/**
+ * ide_plugin_section_get_plugins:
+ * @self: a #IdePluginSection
+ *
+ * A #GListModel of #IdePlugin.
+ *
+ * Returns: (transfer none): a #GListModel
+ */
+GListModel *
+ide_plugin_section_get_plugins (IdePluginSection *self)
+{
+  g_return_val_if_fail (IDE_IS_PLUGIN_SECTION (self), NULL);
+
+  if (self->plugins == NULL)
+    {
+      GtkExpression *expression = gtk_property_expression_new (IDE_TYPE_PLUGIN, NULL, "section");
+      GtkStringFilter *filter = gtk_string_filter_new (expression);
+      GtkFilterListModel *model;
+
+      gtk_string_filter_set_search (filter, self->id);
+      gtk_string_filter_set_match_mode (filter, GTK_STRING_FILTER_MATCH_MODE_EXACT);
+      model = gtk_filter_list_model_new (g_object_ref (_ide_plugin_get_all ()), GTK_FILTER (filter));
+
+      self->plugins = G_LIST_MODEL (model);
+    }
+
+  return self->plugins;
+}
+
+/**
+ * _ide_plugin_section_get_all:
+ *
+ * A #GListModel of #IdePluginSection.
+ *
+ * Returns: (transfer none): a #GListModel
+ */
+GListModel *
+_ide_plugin_section_get_all (void)
+{
+  static GListStore *sections;
+  static const char *section_ids[] = {
+    "editing",
+    "tooling",
+    "projects",
+    "history",
+    "platforms",
+    "integration",
+    "other",
+  };
+
+  if (sections == NULL)
+    {
+      sections = g_list_store_new (IDE_TYPE_PLUGIN_SECTION);
+
+      for (guint i = 0; i < G_N_ELEMENTS (section_ids); i++)
+        {
+          g_autoptr(IdePluginSection) section = NULL;
+
+          section = g_object_new (IDE_TYPE_PLUGIN_SECTION,
+                                  "id", section_ids[i],
+                                  NULL);
+          g_list_store_append (sections, section);
+        }
+    }
+
+  return G_LIST_MODEL (sections);
+}
diff --git a/src/libide/plugins/ide-plugin-section.h b/src/libide/plugins/ide-plugin-section.h
new file mode 100644
index 000000000..1fbc2e2a8
--- /dev/null
+++ b/src/libide/plugins/ide-plugin-section.h
@@ -0,0 +1,43 @@
+/* ide-plugin-section.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_PLUGINS_INSIDE) && !defined (IDE_PLUGINS_COMPILATION)
+# error "Only <libide-plugins.h> can be included directly."
+#endif
+
+#include <libide-core.h>
+
+#include "ide-plugin.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PLUGIN_SECTION (ide_plugin_section_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (IdePluginSection, ide_plugin_section, IDE, PLUGIN_SECTION, GObject)
+
+IDE_AVAILABLE_IN_ALL
+const char *ide_plugin_section_get_id      (IdePluginSection *self);
+IDE_AVAILABLE_IN_ALL
+GListModel *ide_plugin_section_get_plugins (IdePluginSection *self);
+
+G_END_DECLS
diff --git a/src/libide/plugins/ide-plugin.c b/src/libide/plugins/ide-plugin.c
index ce6bbd81d..c6e076d74 100644
--- a/src/libide/plugins/ide-plugin.c
+++ b/src/libide/plugins/ide-plugin.c
@@ -22,7 +22,10 @@
 
 #include "config.h"
 
+#include <glib/gi18n.h>
+
 #include "ide-plugin.h"
+#include "ide-plugin-private.h"
 
 struct _IdePlugin
 {
@@ -32,7 +35,10 @@ struct _IdePlugin
 
 enum {
   PROP_0,
+  PROP_CATEGORY,
+  PROP_CATEGORY_ID,
   PROP_DESCRIPTION,
+  PROP_ID,
   PROP_INFO,
   PROP_NAME,
   PROP_SECTION,
@@ -42,6 +48,7 @@ enum {
 G_DEFINE_FINAL_TYPE (IdePlugin, ide_plugin, G_TYPE_OBJECT)
 
 static GParamSpec *properties [N_PROPS];
+static GHashTable *sections;
 
 static void
 ide_plugin_dispose (GObject *object)
@@ -67,6 +74,10 @@ ide_plugin_get_property (GObject    *object,
 
   switch (prop_id)
     {
+    case PROP_ID:
+      g_value_set_string (value, ide_plugin_get_id (self));
+      break;
+
     case PROP_INFO:
       g_value_set_boxed (value, self->info);
       break;
@@ -75,6 +86,14 @@ ide_plugin_get_property (GObject    *object,
       g_value_set_string (value, ide_plugin_get_name (self));
       break;
 
+    case PROP_CATEGORY:
+      g_value_set_string (value, ide_plugin_get_category (self));
+      break;
+
+    case PROP_CATEGORY_ID:
+      g_value_set_string (value, ide_plugin_get_category_id (self));
+      break;
+
     case PROP_DESCRIPTION:
       g_value_set_string (value, ide_plugin_get_description (self));
       break;
@@ -121,11 +140,26 @@ ide_plugin_class_init (IdePluginClass *klass)
                          PEAS_TYPE_PLUGIN_INFO,
                          (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
 
+  properties[PROP_ID] =
+    g_param_spec_string ("id", NULL, NULL,
+                         NULL,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   properties[PROP_NAME] =
     g_param_spec_string ("name", NULL, NULL,
                          NULL,
                          (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
+  properties[PROP_CATEGORY] =
+    g_param_spec_string ("category", NULL, NULL,
+                         NULL,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  properties[PROP_CATEGORY_ID] =
+    g_param_spec_string ("category-id", NULL, NULL,
+                         NULL,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   properties[PROP_DESCRIPTION] =
     g_param_spec_string ("description", NULL, NULL,
                          NULL,
@@ -176,10 +210,156 @@ ide_plugin_get_description (IdePlugin *self)
   return peas_plugin_info_get_description (self->info);
 }
 
+static void
+ide_plugin_init_sections (void)
+{
+#define ADD_SECTION(category_id, section) \
+  g_hash_table_insert (sections, (char *)category_id, (char *)section)
+
+  if G_UNLIKELY (sections == NULL)
+    {
+      sections = g_hash_table_new (g_str_hash, g_str_equal);
+      ADD_SECTION ("vcs", "history");
+      ADD_SECTION ("sdks", "platforms");
+      ADD_SECTION ("lsps", "tooling");
+      ADD_SECTION ("devices", "platforms");
+      ADD_SECTION ("diagnostics", "tooling");
+      ADD_SECTION ("buildsystems", "projects");
+      ADD_SECTION ("compilers", "tooling");
+      ADD_SECTION ("debuggers", "projects");
+      ADD_SECTION ("templates", "projects");
+      ADD_SECTION ("editing", "editing");
+      ADD_SECTION ("keybindings", "integration");
+      ADD_SECTION ("search", "history");
+      ADD_SECTION ("web", "integration");
+      ADD_SECTION ("language", "tooling");
+      ADD_SECTION ("desktop", "integration");
+      ADD_SECTION ("other", "other");
+    }
+
+#undef ADD_SECTION
+}
+
 const char *
 ide_plugin_get_section (IdePlugin *self)
 {
+  const char *category_id;
+
+  g_return_val_if_fail (IDE_IS_PLUGIN (self), NULL);
+
+  ide_plugin_init_sections ();
+
+  if (!(category_id = peas_plugin_info_get_external_data (self->info, "Category")))
+    category_id = "other";
+
+  return g_hash_table_lookup (sections, category_id);
+}
+
+const char *
+ide_plugin_get_category_id (IdePlugin *self)
+{
+  const char *category_id;
+
   g_return_val_if_fail (IDE_IS_PLUGIN (self), NULL);
 
-  return peas_plugin_info_get_external_data (self->info, "Section");
+  if (!(category_id = peas_plugin_info_get_external_data (self->info, "Category")))
+    category_id = "other";
+
+  return category_id;
+}
+
+const char *
+ide_plugin_get_id (IdePlugin *self)
+{
+  g_return_val_if_fail (IDE_IS_PLUGIN (self), NULL);
+
+  return peas_plugin_info_get_module_name (self->info);
+}
+
+const char *
+ide_plugin_get_category (IdePlugin *self)
+{
+  static GHashTable *titles;
+  const char *category_id;
+
+  g_return_val_if_fail (IDE_IS_PLUGIN (self), NULL);
+
+  if G_UNLIKELY (titles == NULL)
+    {
+      titles = g_hash_table_new (g_str_hash, g_str_equal);
+
+#define ADD_TITLE(category, name) \
+      g_hash_table_insert (titles, (char *)category, (char *)name)
+      ADD_TITLE ("vcs", _("Version Control"));
+      ADD_TITLE ("sdks", _("SDKs"));
+      ADD_TITLE ("lsps", _("Language Servers"));
+      ADD_TITLE ("devices", _("Devices & Simulators"));
+      ADD_TITLE ("diagnostics", _("Diagnostics"));
+      ADD_TITLE ("buildsystems", _("Build Systems"));
+      ADD_TITLE ("compilers", _("Compilers"));
+      ADD_TITLE ("debuggers", _("Debuggers"));
+      ADD_TITLE ("templates", _("Templates"));
+      ADD_TITLE ("editing", _("Editing & Formatting"));
+      ADD_TITLE ("keybindings", _("Keyboard Shortcuts"));
+      ADD_TITLE ("search", _("Search"));
+      ADD_TITLE ("web", _("Web"));
+      ADD_TITLE ("language", _("Language Enablement"));
+      ADD_TITLE ("desktop", _("Desktop Integration"));
+      ADD_TITLE ("other", _("Additional"));
+#undef ADD_TITLE
+    }
+
+  category_id = ide_plugin_get_category_id (self);
+
+  return g_hash_table_lookup (titles, category_id);
+}
+
+static void
+plugin_list_changed_cb (PeasEngine *engine,
+                        GParamSpec *pspec,
+                        GListStore *store)
+{
+  const GList *plugins;
+
+  g_assert (PEAS_IS_ENGINE (engine));
+  g_assert (G_IS_LIST_STORE (store));
+
+  g_list_store_remove_all (store);
+
+  plugins = peas_engine_get_plugin_list (peas_engine_get_default ());
+
+  for (const GList *iter = plugins; iter; iter = iter->next)
+    {
+      const PeasPluginInfo *plugin_info = iter->data;
+      g_autoptr(IdePlugin) plugin = NULL;
+
+      if (peas_plugin_info_is_hidden (plugin_info))
+        continue;
+
+      plugin = g_object_new (IDE_TYPE_PLUGIN,
+                             "info", plugin_info,
+                             NULL);
+      g_list_store_append (store, plugin);
+    }
+}
+
+GListModel *
+_ide_plugin_get_all (void)
+{
+  static GListStore *store;
+
+  if (store == NULL)
+    {
+      PeasEngine *engine = peas_engine_get_default ();
+
+      store = g_list_store_new (IDE_TYPE_PLUGIN);
+      g_signal_connect_object (engine,
+                               "notify::plugin-list",
+                               G_CALLBACK (plugin_list_changed_cb),
+                               store,
+                               0);
+      plugin_list_changed_cb (engine, NULL, store);
+    }
+
+  return G_LIST_MODEL (store);
 }
diff --git a/src/libide/plugins/ide-plugin.h b/src/libide/plugins/ide-plugin.h
index 6675ce2c8..6d486d5c5 100644
--- a/src/libide/plugins/ide-plugin.h
+++ b/src/libide/plugins/ide-plugin.h
@@ -36,12 +36,18 @@ IDE_AVAILABLE_IN_ALL
 G_DECLARE_FINAL_TYPE (IdePlugin, ide_plugin, IDE, PLUGIN, GObject)
 
 IDE_AVAILABLE_IN_ALL
-PeasPluginInfo *ide_plugin_get_info        (IdePlugin *self);
+const char     *ide_plugin_get_id          (IdePlugin *self);
 IDE_AVAILABLE_IN_ALL
-const char     *ide_plugin_get_name        (IdePlugin *self);
+const char     *ide_plugin_get_category    (IdePlugin *self);
+IDE_AVAILABLE_IN_ALL
+const char     *ide_plugin_get_category_id (IdePlugin *self);
 IDE_AVAILABLE_IN_ALL
 const char     *ide_plugin_get_description (IdePlugin *self);
 IDE_AVAILABLE_IN_ALL
+PeasPluginInfo *ide_plugin_get_info        (IdePlugin *self);
+IDE_AVAILABLE_IN_ALL
+const char     *ide_plugin_get_name        (IdePlugin *self);
+IDE_AVAILABLE_IN_ALL
 const char     *ide_plugin_get_section     (IdePlugin *self);
 
 G_END_DECLS
diff --git a/src/libide/plugins/libide-plugins.h b/src/libide/plugins/libide-plugins.h
index 3d3bbf2c8..cdebb1710 100644
--- a/src/libide/plugins/libide-plugins.h
+++ b/src/libide/plugins/libide-plugins.h
@@ -28,6 +28,7 @@ G_BEGIN_DECLS
 # include "ide-extension-adapter.h"
 # include "ide-extension-set-adapter.h"
 # include "ide-plugin.h"
+# include "ide-plugin-section.h"
 #undef IDE_PLUGINS_INSIDE
 
 G_END_DECLS
diff --git a/src/libide/plugins/meson.build b/src/libide/plugins/meson.build
index 8a4d5b844..e607b54ec 100644
--- a/src/libide/plugins/meson.build
+++ b/src/libide/plugins/meson.build
@@ -9,6 +9,7 @@ libide_plugins_public_headers = [
   'ide-extension-adapter.h',
   'ide-extension-set-adapter.h',
   'ide-plugin.h',
+  'ide-plugin-section.h',
   'libide-plugins.h',
 ]
 
@@ -26,6 +27,7 @@ libide_plugins_public_sources = [
   'ide-extension-adapter.c',
   'ide-extension-set-adapter.c',
   'ide-plugin.c',
+  'ide-plugin-section.c',
 ]
 
 libide_plugins_private_sources = [
@@ -39,6 +41,8 @@ libide_plugins_private_sources = [
 libide_plugins_deps = [
   libgio_dep,
   libpeas_dep,
+  libgtk_dep,
+
   libide_core_dep,
 ]
 


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