[gnome-builder/wip/gtk4-port: 1509/1774] libide/gui: add IdeShortcutProvider interface




commit 143879ba333fc822a3531fde0a6b784f97c4d605
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jun 14 13:38:29 2022 -0700

    libide/gui: add IdeShortcutProvider interface
    
    This is meant to be a plugin interface where more control over shortcuts
    is needed, or perhaps even dynamic control over them. The initial use of
    this is to allow shellcmd to provide keybindings based on those that are
    defined in org.gnome.builder.shellcmd.command gschema.

 src/libide/gui/ide-shortcut-manager.c  | 109 +++++++++++++++++++++++++++++++++
 src/libide/gui/ide-shortcut-provider.c |  68 ++++++++++++++++++++
 src/libide/gui/ide-shortcut-provider.h |  46 ++++++++++++++
 src/libide/gui/libide-gui.h            |   1 +
 src/libide/gui/meson.build             |   2 +
 5 files changed, 226 insertions(+)
---
diff --git a/src/libide/gui/ide-shortcut-manager.c b/src/libide/gui/ide-shortcut-manager.c
index f2c54a9c1..3893e2b5b 100644
--- a/src/libide/gui/ide-shortcut-manager.c
+++ b/src/libide/gui/ide-shortcut-manager.c
@@ -24,8 +24,11 @@
 
 #include <gtk/gtk.h>
 
+#include <libide-plugins.h>
+
 #include "ide-shortcut-bundle-private.h"
 #include "ide-shortcut-manager-private.h"
+#include "ide-shortcut-provider.h"
 
 struct _IdeShortcutManager
 {
@@ -47,6 +50,10 @@ struct _IdeShortcutManager
 
   /* A flattened list model we proxy through our interface */
   GtkFlattenListModel *flatten;
+
+  /* Extension set of IdeShortcutProvider */
+  IdeExtensionSetAdapter *providers;
+  GListStore *providers_models;
 };
 
 static GType
@@ -135,11 +142,105 @@ ide_shortcut_manager_items_changed_cb (IdeShortcutManager *self,
   g_list_model_items_changed (G_LIST_MODEL (self), position, removed, added);
 }
 
+static void
+on_provider_added_cb (IdeExtensionSetAdapter *set,
+                      PeasPluginInfo         *plugin_info,
+                      PeasExtension          *exten,
+                      gpointer                user_data)
+{
+  IdeShortcutProvider *provider = (IdeShortcutProvider *)exten;
+  IdeShortcutManager *self = user_data;
+  g_autoptr(GListModel) model = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (set));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_SHORTCUT_PROVIDER (provider));
+
+  if ((model = ide_shortcut_provider_list_shortcuts (provider)))
+    {
+      g_object_set_data (G_OBJECT (provider), "SHORTCUTS_MODEL", model);
+      g_list_store_append (self->providers_models, model);
+    }
+
+  IDE_EXIT;
+}
+
+static void
+on_provider_removed_cb (IdeExtensionSetAdapter *set,
+                        PeasPluginInfo         *plugin_info,
+                        PeasExtension          *exten,
+                        gpointer                user_data)
+{
+  IdeShortcutProvider *provider = (IdeShortcutProvider *)exten;
+  IdeShortcutManager *self = user_data;
+  GListModel *model;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_EXTENSION_SET_ADAPTER (set));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_SHORTCUT_PROVIDER (provider));
+
+  if ((model = g_object_get_data (G_OBJECT (provider), "SHORTCUTS_MODEL")))
+    {
+      guint n_items = g_list_model_get_n_items (G_LIST_MODEL (self->providers_models));
+
+      for (guint i = 0; i < n_items; i++)
+        {
+          g_autoptr(GListModel) item = g_list_model_get_item (G_LIST_MODEL (self->providers_models), i);
+
+          if (item == model)
+            {
+              g_list_store_remove (self->providers_models, i);
+              break;
+            }
+        }
+    }
+
+  IDE_EXIT;
+}
+
+static void
+ide_shortcut_manager_parent_set (IdeObject *object,
+                                 IdeObject *parent)
+{
+  IdeShortcutManager *self = (IdeShortcutManager *)object;
+
+  g_assert (IDE_IS_SHORTCUT_MANAGER (self));
+  g_assert (!parent || IDE_IS_OBJECT (parent));
+
+  if (parent == NULL)
+    return;
+
+  if (self->providers == NULL)
+    {
+      self->providers = ide_extension_set_adapter_new (IDE_OBJECT (self),
+                                                       peas_engine_get_default (),
+                                                       IDE_TYPE_SHORTCUT_PROVIDER,
+                                                       NULL, NULL);
+      g_signal_connect (self->providers,
+                        "extension-added",
+                        G_CALLBACK (on_provider_added_cb),
+                        self);
+      g_signal_connect (self->providers,
+                        "extension-removed",
+                        G_CALLBACK (on_provider_removed_cb),
+                        self);
+      ide_extension_set_adapter_foreach_by_priority (self->providers,
+                                                     on_provider_added_cb,
+                                                     self);
+    }
+}
+
 static void
 ide_shortcut_manager_dispose (GObject *object)
 {
   IdeShortcutManager *self = (IdeShortcutManager *)object;
 
+  g_clear_object (&self->providers);
+  g_clear_object (&self->providers_models);
   g_clear_object (&self->toplevel);
   g_clear_object (&self->plugin_models);
   g_clear_object (&self->flatten);
@@ -151,8 +252,13 @@ static void
 ide_shortcut_manager_class_init (IdeShortcutManagerClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  IdeObjectClass *i_object_class = IDE_OBJECT_CLASS (klass);
 
   object_class->dispose = ide_shortcut_manager_dispose;
+
+  i_object_class->parent_set = ide_shortcut_manager_parent_set;
+
+  g_type_ensure (IDE_TYPE_SHORTCUT_PROVIDER);
 }
 
 static void
@@ -165,6 +271,9 @@ ide_shortcut_manager_init (IdeShortcutManager *self)
 
   self->toplevel = g_list_store_new (G_TYPE_LIST_MODEL);
   self->plugin_models = g_object_ref (plugin_models);
+  self->providers_models = g_list_store_new (G_TYPE_LIST_MODEL);
+
+  g_list_store_append (self->toplevel, self->providers_models);
 
   flatten = gtk_flatten_list_model_new (g_object_ref (G_LIST_MODEL (self->plugin_models)));
   g_list_store_append (self->toplevel, flatten);
diff --git a/src/libide/gui/ide-shortcut-provider.c b/src/libide/gui/ide-shortcut-provider.c
new file mode 100644
index 000000000..05b6a87c7
--- /dev/null
+++ b/src/libide/gui/ide-shortcut-provider.c
@@ -0,0 +1,68 @@
+/* ide-shortcut-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-shortcut-provider"
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "ide-shortcut-provider.h"
+
+G_DEFINE_INTERFACE (IdeShortcutProvider, ide_shortcut_provider, IDE_TYPE_OBJECT)
+
+static GListModel *
+ide_shortcut_provider_real_list_shortcuts (IdeShortcutProvider *self)
+{
+  return G_LIST_MODEL (g_list_store_new (GTK_TYPE_SHORTCUT));
+}
+
+static void
+ide_shortcut_provider_default_init (IdeShortcutProviderInterface *iface)
+{
+  iface->list_shortcuts = ide_shortcut_provider_real_list_shortcuts;
+}
+
+/**
+ * ide_shortcut_provider_list_shortcuts:
+ * @self: a #IdeShortcutProvider
+ *
+ * Gets a #GListModel of #GtkShortcut.
+ *
+ * This function should return a #GListModel of #GtkShortcut that are updated
+ * as necessary by the plugin. This list model is used to activate shortcuts
+ * based on user input and allows more control by plugins over when and how
+ * shortcuts may activate.
+ *
+ * Returns: (transfer full): A #GListModel of #GtkShortcut
+ */
+GListModel *
+ide_shortcut_provider_list_shortcuts (IdeShortcutProvider *self)
+{
+  GListModel *ret;
+
+  IDE_ENTRY;
+
+  g_return_val_if_fail (IDE_IS_SHORTCUT_PROVIDER (self), NULL);
+
+  ret = IDE_SHORTCUT_PROVIDER_GET_IFACE (self)->list_shortcuts (self);
+
+  IDE_RETURN (ret);
+}
diff --git a/src/libide/gui/ide-shortcut-provider.h b/src/libide/gui/ide-shortcut-provider.h
new file mode 100644
index 000000000..8c4c75e70
--- /dev/null
+++ b/src/libide/gui/ide-shortcut-provider.h
@@ -0,0 +1,46 @@
+/* ide-shortcut-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_GUI_INSIDE) && !defined (IDE_GUI_COMPILATION)
+# error "Only <libide-gui.h> can be included directly."
+#endif
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SHORTCUT_PROVIDER (ide_shortcut_provider_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_INTERFACE (IdeShortcutProvider, ide_shortcut_provider, IDE, SHORTCUT_PROVIDER, IdeObject)
+
+struct _IdeShortcutProviderInterface
+{
+  GTypeInterface parent_iface;
+
+  GListModel *(*list_shortcuts) (IdeShortcutProvider *self);
+};
+
+IDE_AVAILABLE_IN_ALL
+GListModel *ide_shortcut_provider_list_shortcuts (IdeShortcutProvider *self);
+
+G_END_DECLS
diff --git a/src/libide/gui/libide-gui.h b/src/libide/gui/libide-gui.h
index 25accaccc..57fa3deb7 100644
--- a/src/libide/gui/libide-gui.h
+++ b/src/libide/gui/libide-gui.h
@@ -54,6 +54,7 @@
 # include "ide-run-button.h"
 # include "ide-search-popover.h"
 # include "ide-session-addin.h"
+# include "ide-shortcut-provider.h"
 # include "ide-workbench.h"
 # include "ide-workbench-addin.h"
 # include "ide-workspace.h"
diff --git a/src/libide/gui/meson.build b/src/libide/gui/meson.build
index df09c7006..40dc85479 100644
--- a/src/libide/gui/meson.build
+++ b/src/libide/gui/meson.build
@@ -32,6 +32,7 @@ libide_gui_public_headers = [
   'ide-run-button.h',
   'ide-search-popover.h',
   'ide-session-addin.h',
+  'ide-shortcut-provider.h',
   'ide-workbench.h',
   'ide-workbench-addin.h',
   'ide-workspace.h',
@@ -107,6 +108,7 @@ libide_gui_public_sources = [
   'ide-preferences-window.c',
   'ide-run-button.c',
   'ide-session-addin.c',
+  'ide-shortcut-provider.c',
   'ide-workbench.c',
   'ide-workbench-addin.c',
   'ide-workspace.c',


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