GtkApplication: Extract accelerators from menus

This allows to specify accelerators in a convenient way, by
adding accel="..." attributes to the menu items in the
XML for the menu.

Currently, the accelerators are extracted only once, when the
menu property is changed on the application.
This commit is contained in:
Matthias Clasen 2011-12-05 17:41:56 -05:00 committed by Ryan Lortie
parent 2398d7e900
commit f7244431a9

View File

@ -347,11 +347,89 @@ gtk_application_window_removed (GtkApplication *application,
gtk_window_set_application (window, NULL);
}
static void
extract_accel_from_menu_item (GMenuModel *model,
gint item,
GtkApplication *app)
{
GMenuAttributeIter *iter;
const gchar *key;
GVariant *value;
const gchar *accel = NULL;
const gchar *action = NULL;
GVariant *target = NULL;
iter = g_menu_model_iterate_item_attributes (model, item);
while (g_menu_attribute_iter_get_next (iter, &key, &value))
{
if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
action = g_variant_get_string (value, NULL);
else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
accel = g_variant_get_string (value, NULL);
else if (g_str_equal (key, "target"))
target = g_variant_ref (value);
g_variant_unref (value);
}
g_object_unref (iter);
if (accel && action)
gtk_application_add_accelerator (app, accel, action, target);
if (target)
g_variant_unref (target);
}
static void
extract_accels_from_menu (GMenuModel *model,
GtkApplication *app)
{
gint i;
GMenuLinkIter *iter;
const gchar *key;
GMenuModel *m;
for (i = 0; i < g_menu_model_get_n_items (model); i++)
{
extract_accel_from_menu_item (model, i, app);
iter = g_menu_model_iterate_item_links (model, i);
while (g_menu_link_iter_get_next (iter, &key, &m))
{
extract_accels_from_menu (m, app);
g_object_unref (m);
}
g_object_unref (iter);
}
}
static void
gtk_application_notify (GObject *object,
GParamSpec *pspec)
{
if (strcmp (pspec->name, "app-menu") == 0 ||
strcmp (pspec->name, "menubar") == 0)
{
GMenuModel *model;
g_object_get (object, pspec->name, &model, NULL);
if (model)
{
extract_accels_from_menu (model, GTK_APPLICATION (object));
g_object_unref (model);
}
}
if (G_OBJECT_CLASS (gtk_application_parent_class)->notify)
G_OBJECT_CLASS (gtk_application_parent_class)->notify (object, pspec);
}
static void
gtk_application_class_init (GtkApplicationClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GApplicationClass *application_class = G_APPLICATION_CLASS (class);
object_class->notify = gtk_application_notify;
application_class->add_platform_data = gtk_application_add_platform_data;
application_class->before_emit = gtk_application_before_emit;
application_class->after_emit = gtk_application_after_emit;