[gnome-builder] libide/gui: improve shortcut discovery
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] libide/gui: improve shortcut discovery
- Date: Tue, 4 Oct 2022 04:40:50 +0000 (UTC)
commit 6e53e2db10c93a8ef6e718b47408e3a6f0885577
Author: Christian Hergert <chergert redhat com>
Date: Mon Oct 3 21:38:12 2022 -0700
libide/gui: improve shortcut discovery
src/libide/gui/ide-shortcut-bundle-private.h | 11 +++++
src/libide/gui/ide-shortcut-bundle.c | 16 +++-----
src/libide/gui/ide-shortcut-info.h | 3 +-
src/libide/gui/ide-shortcut-window.c | 61 ++++++++++++++++++++++++----
4 files changed, 71 insertions(+), 20 deletions(-)
---
diff --git a/src/libide/gui/ide-shortcut-bundle-private.h b/src/libide/gui/ide-shortcut-bundle-private.h
index 1f8ec5183..6d67cfa8e 100644
--- a/src/libide/gui/ide-shortcut-bundle-private.h
+++ b/src/libide/gui/ide-shortcut-bundle-private.h
@@ -20,12 +20,23 @@
#pragma once
+#include <gtk/gtk.h>
+#include <tmpl-glib.h>
+
#include <libide-core.h>
G_BEGIN_DECLS
#define IDE_TYPE_SHORTCUT_BUNDLE (ide_shortcut_bundle_get_type())
+typedef struct
+{
+ TmplExpr *when;
+ GVariant *args;
+ GtkShortcutAction *action;
+ GtkPropagationPhase phase;
+} IdeShortcut;
+
G_DECLARE_FINAL_TYPE (IdeShortcutBundle, ide_shortcut_bundle, IDE, SHORTCUT_BUNDLE, GObject)
IdeShortcutBundle *ide_shortcut_bundle_new (void);
diff --git a/src/libide/gui/ide-shortcut-bundle.c b/src/libide/gui/ide-shortcut-bundle.c
index df23db0e1..83cac9632 100644
--- a/src/libide/gui/ide-shortcut-bundle.c
+++ b/src/libide/gui/ide-shortcut-bundle.c
@@ -38,14 +38,6 @@ struct _IdeShortcutBundle
GPtrArray *items;
};
-typedef struct
-{
- TmplExpr *when;
- GVariant *args;
- GtkShortcutAction *action;
- GtkPropagationPhase phase;
-} IdeShortcut;
-
static TmplScope *imports_scope;
static IdeShortcut *
@@ -61,7 +53,7 @@ ide_shortcut_new (const char *action,
ret = g_slice_new0 (IdeShortcut);
ret->action = gtk_named_action_new (action);
- ret->args = args ? g_variant_ref (args) : NULL;
+ ret->args = args ? g_variant_ref_sink (args) : NULL;
ret->when = when ? tmpl_expr_ref (when) : NULL;
ret->phase = phase;
@@ -315,6 +307,7 @@ populate_from_object (IdeShortcutBundle *self,
const char *phase_str = NULL;
const char *command = NULL;
const char *action = NULL;
+ IdeShortcut *state;
GtkPropagationPhase phase = 0;
JsonObject *obj;
@@ -396,12 +389,13 @@ populate_from_object (IdeShortcutBundle *self,
return FALSE;
}
- callback = gtk_callback_action_new (ide_shortcut_activate,
- ide_shortcut_new (action, args, when, phase),
+ state = ide_shortcut_new (action, args, when, phase);
+ callback = gtk_callback_action_new (ide_shortcut_activate, state,
(GDestroyNotify) ide_shortcut_free);
shortcut = gtk_shortcut_new (g_steal_pointer (&trigger),
g_steal_pointer (&callback));
g_object_set_data (G_OBJECT (shortcut), "PHASE", GINT_TO_POINTER (phase));
+ g_object_set_data (G_OBJECT (shortcut), "IDE_SHORTCUT", state);
g_ptr_array_add (self->items, g_steal_pointer (&shortcut));
return TRUE;
diff --git a/src/libide/gui/ide-shortcut-info.h b/src/libide/gui/ide-shortcut-info.h
index 0e6249d4a..fda0b3fca 100644
--- a/src/libide/gui/ide-shortcut-info.h
+++ b/src/libide/gui/ide-shortcut-info.h
@@ -30,7 +30,8 @@ typedef void (*IdeShortcutInfoFunc) (const IdeShortcutInfo *info,
gpointer user_data);
IDE_AVAILABLE_IN_44
-void ide_shortcut_info_foreach (const IdeShortcutInfoFunc func,
+void ide_shortcut_info_foreach (GListModel *shortcuts,
+ const IdeShortcutInfoFunc func,
gpointer func_data);
IDE_AVAILABLE_IN_44
const char *ide_shortcut_info_get_accelerator (const IdeShortcutInfo *self);
diff --git a/src/libide/gui/ide-shortcut-window.c b/src/libide/gui/ide-shortcut-window.c
index a52829c7d..d8849e77c 100644
--- a/src/libide/gui/ide-shortcut-window.c
+++ b/src/libide/gui/ide-shortcut-window.c
@@ -27,6 +27,7 @@
#include <libide-gtk.h>
#include "ide-application-private.h"
+#include "ide-shortcut-bundle-private.h"
#include "ide-shortcut-info.h"
#include "ide-shortcut-window-private.h"
@@ -118,7 +119,7 @@ page_info_free (PageInfo *pi)
g_slice_free (PageInfo, pi);
}
-static const char *
+static char *
find_accel_for_action (GHashTable *accel_map,
const char *action)
{
@@ -132,7 +133,7 @@ find_accel_for_action (GHashTable *accel_map,
return NULL;
if ((accel = g_hash_table_lookup (accel_map, action)))
- return accel;
+ return g_strdup (accel);
if ((split = strstr (action, "::")))
alt = g_strdup (split + 2);
@@ -141,7 +142,7 @@ find_accel_for_action (GHashTable *accel_map,
else
return NULL;
- return g_hash_table_lookup (accel_map, alt);
+ return g_strdup (g_hash_table_lookup (accel_map, alt));
}
static void
@@ -165,11 +166,11 @@ populate_from_menu_model (GQueue *queue,
g_autofree char *icon_name = NULL;
g_autofree char *item_group = NULL;
g_autofree char *item_page = NULL;
+ g_autofree char *accel = NULL;
g_autofree char *subtitle = NULL;
g_autofree char *title = NULL;
g_autoptr(GVariant) target = NULL;
ShortcutInfo *si;
- const char *accel;
if (!g_menu_model_get_item_attribute (menu, i, "action", "s", &action))
continue;
@@ -190,7 +191,7 @@ populate_from_menu_model (GQueue *queue,
si = g_slice_new0 (ShortcutInfo);
si->link.data = si;
- si->accel = g_strdup (accel);
+ si->accel = g_steal_pointer (&accel);
si->icon_name = g_steal_pointer (&icon_name);
si->subtitle = g_steal_pointer (&subtitle);
si->title = g_steal_pointer (&title);
@@ -524,17 +525,61 @@ struct _IdeShortcutInfo
GVariant *action_target;
};
+/**
+ * ide_shortcut_info_foreach:
+ * @shortcuts: a #GListModel of #GtkShortcut
+ * @func: (scope call): a callback for each shortcut info
+ * @func_data: closure data for @func
+ *
+ * Calls @func for every shortcut info. Accelerators come from
+ * @shortcuts by matching action and target.
+ */
void
-ide_shortcut_info_foreach (const IdeShortcutInfoFunc func,
- gpointer func_data)
+ide_shortcut_info_foreach (GListModel *shortcuts,
+ const IdeShortcutInfoFunc func,
+ gpointer func_data)
{
g_autoptr(GHashTable) accel_map = NULL;
GQueue pages = G_QUEUE_INIT;
IdeShortcutInfo info = {0};
g_return_if_fail (func != NULL);
+ g_return_if_fail (!shortcuts || G_IS_LIST_MODEL (shortcuts));
+
+ accel_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ if (shortcuts != NULL)
+ {
+ guint n_items = g_list_model_get_n_items (shortcuts);
+
+ /* First build a hashmap of action names to shortcut triggers */
+ for (guint i = n_items; i > 0; i--)
+ {
+ g_autoptr(GtkShortcut) shortcut = g_list_model_get_item (shortcuts, i-1);
+ GtkShortcutTrigger *trigger = gtk_shortcut_get_trigger (shortcut);
+ GtkShortcutAction *action = gtk_shortcut_get_action (shortcut);
+ IdeShortcut *state;
+
+ if (GTK_IS_NAMED_ACTION (action))
+ {
+ g_autofree char *accel = gtk_shortcut_trigger_to_string (trigger);
+ const char *name = gtk_named_action_get_action_name (GTK_NAMED_ACTION (action));
+
+ g_hash_table_insert (accel_map, g_strdup (name), g_steal_pointer (&accel));
+ }
+ else if ((state = g_object_get_data (G_OBJECT (shortcut), "IDE_SHORTCUT")) &&
+ GTK_IS_NAMED_ACTION (state->action))
+ {
+ g_autofree char *accel = gtk_shortcut_trigger_to_string (trigger);
+ const char *name = gtk_named_action_get_action_name (GTK_NAMED_ACTION (state->action));
+
+ g_hash_table_insert (accel_map,
+ g_strdup (name),
+ g_steal_pointer (&accel));
+ }
+ }
+ }
- accel_map = g_hash_table_new (NULL, NULL);
populate_info (&pages, accel_map);
for (const GList *piter = pages.head; piter; piter = piter->next)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]