This post is meant for new developers to GIO/GTK who want to get an idea of how things are connected. You will learn about the interaction between the interfaces, look at the big picture and also see example code.
Putting in Picture GIO's GAction*
This tip tries to put up a picture of the following:
GAction
GActionGroup
GActionMap
GActionEntry
GSimpleAction
GSimpleActionGroup
Who Is This For?
New developers to GIO/GTK, who just stumbled across the GAction-family and want to get a "bigger picture" of how things are connected.
Links to Related Information
Essence Regarding Usage
You probably don't need GAction
or GSimpleAction
. Using them is tedious and more difficult.
Interaction Between Interfaces
GAction
, GActionGroup
and GActionMap
are interfaces. The following image shows how the interfaces work together.
- Several
GAction
s can be put into a GActionGroup
. Several GActionGroups
can be put into a GActionMap
- Actions have names
- Groups have names
- Action maps gather all actions with their full name
The Big Picture
The following image shows which interfaces are implemented by which classes:
- The greyed out
GAction
part is what you probably don't need. Using it (especially in C) is unintuitive and very tedious (keyword: casting). - Instead of a
GAction
, you use a GActionEntry
. - Inheritance in black color can be understood as:
GApplication
contains a GActionGroup
GApplication
contains a GActionMap
GSimpleActionGroup
contains a GActionGroup
GSimpleActionGroup
contains a GActionMap
- A
GSimpleActionGroup
can be created and inserted into a GtkWidget (using gtk_widget_insert_action_group
). That way, you can add specific actions to widgets. That way, you can set a new (, local) shortcut (accelerator) for that widget.
Example Code
The following is a fully functional C example code creating a GMenu
and attaching GActions
to it.
#include <gtk/gtk.h>
#include <stdio.h>
GMenuModel * createMenu(){
GMenu * menu = g_menu_new();
{
g_menu_append(menu, "Item1", "app.item1_action1");
g_menu_append(menu, "Item2", "app.item2_action1");
GMenu * submenu = g_menu_new();
{
g_menu_append(submenu, "Subitem1", "subaction1");
g_menu_append_submenu(menu,"Submenu1",(GMenuModel*)submenu);
}
}
return (GMenuModel*)menu;
}
void exampleAction (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
printf("hello world\n");
}
static void
activate (GApplication *app,
gpointer user_data)
{
GtkWindow *window = (GtkWindow*)gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_default_size (window, 200, 200);
gtk_window_set_position (window, GTK_WIN_POS_CENTER);
GMenuModel * menu = createMenu();
gtk_application_set_app_menu(GTK_APPLICATION(app), (GMenuModel*)menu);
g_object_unref (menu);
{
GActionEntry actions[] = {
{"item1_action1", exampleAction, NULL, NULL, NULL}
};
g_action_map_add_action_entries(G_ACTION_MAP(app),actions, 1, NULL);
GAction * action = (GAction*)g_simple_action_new("item2_action1",NULL);
g_signal_connect(action, "activate", G_CALLBACK(exampleAction), NULL);
g_action_map_add_action(G_ACTION_MAP(app), action);
}
gtk_widget_show_all ((GtkWidget*)window);
}
int
main (int argc, char *argv[])
{
GtkApplication * app = gtk_application_new(NULL,G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK (activate), NULL);
int status = g_application_run(G_APPLICATION (app), argc, argv);
g_object_unref(app);
return status;
}
History
- 2nd May, 2020: Initial version