Hi there,
I’m using GtkBuilder
with xml files to build menus and connect handlers with an array of GActionEntry
s.
This works for simple stateless actions and boolean and string targets.
I cannot however get menu items (a section to create radio buttons) to work using integer (or double) targets, they’re greyed out. When I change parameter_type
to string (“s”), the handler is called, with a string in the GVariant.
Here’s a snippet of the code with the handlers:
static void on_set_magnification(GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
gint32 i = g_variant_get_int32(parameter);
g_print("%s(): got magnification of %d%%\n", __func__, i);
g_simple_action_set_state(action, parameter);
}
static void on_foo(GSimpleAction *action,
GVariant *parameter,
gpointer data)
{
g_print("FOO!\n");
}
static const GActionEntry preview_actions[] = {
{
.name = "close",
.activate = on_close,
},
{
.name = "set-magnification",
.parameter_type = "i",
.state = "100",
.change_state = on_set_magnification,
},
{
.name = "foo",
.activate = on_foo
}
};
GtkWidget *ui_preview_window_new(GtkApplication *app)
{
GtkBuilder *builder;
GMenuModel *menu;
GtkWidget *header;
GtkWidget *grid;
GtkWidget *primary;
GtkWidget *secondary;
if (preview_window != NULL) {
gtk_window_present(GTK_WINDOW(preview_window));
return preview_window;
}
preview_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
header = gtk_header_bar_new();
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header), TRUE);
primary = gtk_menu_button_new();
gtk_header_bar_pack_start(GTK_HEADER_BAR(header), primary);
builder = gtk_builder_new_from_resource(RESOURCE_PREFIX
"/ui/preview-window-main.ui");
menu = G_MENU_MODEL(gtk_builder_get_object(builder, "main-menu"));
gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(primary), menu);
g_object_unref(builder);
secondary = gtk_menu_button_new();
gtk_header_bar_pack_end(GTK_HEADER_BAR(header), secondary);
builder = gtk_builder_new_from_resource(RESOURCE_PREFIX
"/ui/preview-window-gears.ui");
menu = G_MENU_MODEL(gtk_builder_get_object(builder, "gears-menu"));
gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(secondary), menu);
g_object_unref(builder);
gtk_header_bar_set_title(GTK_HEADER_BAR(header), "Preview");
gtk_window_set_titlebar(GTK_WINDOW(preview_window), header);
grid = gtk_grid_new();
preview_area = preview_create();
gtk_grid_attach(GTK_GRID(grid), preview_area, 0, 0, 1, 1);
gtk_container_add(GTK_CONTAINER(preview_window), grid);
action_group = g_simple_action_group_new();
g_action_map_add_action_entries(G_ACTION_MAP(action_group),
preview_actions,
G_N_ELEMENTS(preview_actions),
preview_window);
gtk_widget_insert_action_group(preview_window, "preview", G_ACTION_GROUP(action_group));
g_signal_connect(preview_window,
"destroy",
G_CALLBACK(on_destroy),
NULL);
g_signal_connect(preview_window,
"delete-event",
G_CALLBACK(on_delete_event),
NULL);
return preview_window;
}
And here’s the UI file:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="gears-menu">
<section>
<item>
<attribute name="label">100%</attribute>
<attribute name="action">preview.set-magnification</attribute>
<attribute name="target">100</attribute>
</item>
<item>
<attribute name="label">150%</attribute>
<attribute name="action">preview.set-magnification</attribute>
<attribute name="target">150</attribute>
</item>
<item>
<attribute name="label">200%</attribute>
<attribute name="action">preview.set-magnification</attribute>
<attribute name="target">200</attribute>
</item>
<item>
<attribute name="label">300%</attribute>
<attribute name="action">preview.set-magnification</attribute>
<attribute name="target">300</attribute>
</item>
<item>
<attribute name="label">400%</attribute>
<attribute name="action">preview.set-magnification</attribute>
<attribute name="target">400</attribute>
</item>
</section>
<section>
<item>
<attribute name="label">Foo</attribute>
<attribute name="action">preview.foo</attribute>
</item>
</section>
</menu>
</interface>
The ‘foo’ action works, it prints on stdout. The integer targets for set-magnification
however do not. When I change the parameter type to string then the actions get triggered.
I’ve tried prefixing the .state
with “i” and “int32”, etc, I tried prefixing the targets in the XML with “i” “int32”, etc, I can’t get it to work.
I could, as a workaround, use strings and then convert the string to int in the action handler, but that seems silly when GVariant can hold a whole bunch of different types.
So can anyone spot where I’m messing up, or perhaps point me to examples of GActionEntry’s with non-bool/non-string values?
Thanks.
EDIT: I forgot to mention I’m using Gtk+ 3.24.26 and GLib 2.66.8