After I managed to succeed to recreate the gtk-demo-application with GMenu
and Actions to be more sure that I am understanding how Actions
works, I decided to create for every item an individual action with the following two functions:
g_simple_action_new()
g_simple_action_new_stateful()
And everything works fine, but there is something what I can not figure out where and what I missing.
The problem is when I create a BOOLEAN
state like here:
GVariant *state;
state = g_variant_new_boolean ( TRUE );
mic_action = g_simple_action_new_stateful ( "microphone", NULL, state );
if I pass, NULL
as the second parameter everything works fine, but with the following:
mic_action = g_simple_action_new_stateful ( "microphone", G_VARIANT_TYPE_BOOLEAN, state );
The item is not activatable anymore.
Here the code which describes the problem:
#include <gtk/gtk.h>
static void red_clbk ( GSimpleAction *action, GVariant *parameter )
{
g_print ( "Action `%s` Selected '%s'\n", g_action_get_name ( G_ACTION ( action ) ), g_variant_get_string ( parameter, NULL ) );
}
static void green_clbk ( GSimpleAction *action, GVariant *parameter )
{
g_print ( "Action `%s` Selected '%s'\n", g_action_get_name ( G_ACTION ( action ) ), g_variant_get_string ( parameter, NULL ) );
}
static void blue_clbk ( GSimpleAction *action, GVariant *parameter )
{
g_print ( "Action `%s` Selected '%s'\n", g_action_get_name ( G_ACTION ( action ) ), g_variant_get_string ( parameter, NULL ) );
}
static void create_item ( GMenu *menu,
const gchar *const label,
const gchar *const action,
const gchar *const icon,
const gchar *const target,
const gchar *const accel )
{
g_return_if_fail ( G_IS_MENU ( menu ) );
GMenuItem *item = g_menu_item_new ( NULL, NULL );
g_menu_item_set_attribute ( item, G_MENU_ATTRIBUTE_LABEL, "s", label, NULL );
g_menu_item_set_attribute ( item, G_MENU_ATTRIBUTE_ACTION, "s", action, NULL );
g_menu_item_set_attribute ( item, G_MENU_ATTRIBUTE_ICON, "s", icon, NULL );
if ( target )
{
g_menu_item_set_attribute ( item, "target", "s", target, NULL );
}
g_menu_item_set_attribute ( item, "accel", "s", accel, NULL );
g_menu_append_item ( menu, item );
g_object_unref ( item );
}
static void create_submenu_item ( GMenu *menu,
GMenu *submenu,
const gchar *const label )
{
g_return_if_fail ( G_IS_MENU ( menu ) );
GMenuItem *item = g_menu_item_new ( NULL, NULL );
g_menu_item_set_attribute ( item, G_MENU_ATTRIBUTE_LABEL, "s", label, NULL );
g_menu_item_set_submenu ( item, G_MENU_MODEL ( submenu ) );
g_menu_append_item ( menu, item );
g_object_unref ( item );
}
static void open_clbk ( GSimpleAction *action,
G_GNUC_UNUSED GVariant *parameter )
{
g_print ( "Action `%s` Called\n", g_action_get_name ( G_ACTION ( action ) ) );
}
static void activate_radio ( GSimpleAction *action, GVariant *parameter, G_GNUC_UNUSED gpointer user_data )
{
g_action_change_state ( G_ACTION ( action ), parameter );
const gchar *attribut;
attribut = g_variant_get_string ( parameter, NULL );
if ( g_strcmp0 ( attribut, "red" ) == 0 )
{
red_clbk ( action, parameter );
}
else if ( g_strcmp0 ( attribut, "green" ) == 0 )
{
green_clbk ( action, parameter );
}
else if ( g_strcmp0 ( attribut, "blue" ) == 0 )
{
blue_clbk ( action, parameter );
}
else
{
g_assert_not_reached ();
}
}
static void change_radio_state ( GSimpleAction *action, GVariant *state, G_GNUC_UNUSED gpointer user_data )
{
g_simple_action_set_state ( action, state );
activate_radio ( action, state, user_data );
}
static void mic_check_clbk ( GSimpleAction *action, G_GNUC_UNUSED GVariant *parameter )
{
GVariant *action_state;
action_state = g_action_get_state ( G_ACTION ( action ) );
if ( g_variant_get_boolean ( action_state ) == FALSE )
{
g_simple_action_set_state ( action, g_variant_new_boolean ( TRUE ) );
g_print ( "Microfon Activated.\n" );
}
else
{
g_simple_action_set_state ( action, g_variant_new_boolean ( FALSE ) );
g_print ( "\tMicrofon deactivated.\n" );
}
}
static void startup ( GtkApplication *application )
{
GMenu *main_menu;
GMenu *file_menu;
GSimpleAction *webcam_action;
GSimpleAction *mic_action;
GSimpleAction *color_action;
GSimpleAction *red_action;
GSimpleAction *green_action;
GSimpleAction *blue_action;
/// ***
webcam_action = g_simple_action_new ( "webcam", NULL );
GVariant *state_color;
state_color = g_variant_new_string ( "green" );
color_action = g_simple_action_new_stateful ( "color", G_VARIANT_TYPE_STRING, state_color );
red_action = g_simple_action_new ( "red", NULL );
green_action = g_simple_action_new ( "green", NULL );
blue_action = g_simple_action_new ( "blue", NULL );
/// ***
GVariant *state;
state = g_variant_new_boolean ( TRUE );
/// *** THIS does not seem to work!!!!!!!!!!!!!!!
///mic_action = g_simple_action_new_stateful ( "microphone", G_VARIANT_TYPE_BOOLEAN, state );
/// *** But THIS works fine.
mic_action = g_simple_action_new_stateful ( "microphone", NULL, state );
/// ***
g_signal_connect_swapped ( webcam_action, "activate", G_CALLBACK ( open_clbk ), webcam_action );
g_signal_connect ( mic_action, "activate", G_CALLBACK ( mic_check_clbk ), mic_action );
g_signal_connect ( color_action, "activate", G_CALLBACK ( change_radio_state ), color_action );
g_action_map_add_action ( G_ACTION_MAP ( application ), G_ACTION ( webcam_action ) );
g_action_map_add_action ( G_ACTION_MAP ( application ), G_ACTION ( mic_action ) );
g_action_map_add_action ( G_ACTION_MAP ( application ), G_ACTION ( color_action ) );
g_action_map_add_action ( G_ACTION_MAP ( application ), G_ACTION ( red_action ) );
g_action_map_add_action ( G_ACTION_MAP ( application ), G_ACTION ( green_action ) );
g_action_map_add_action ( G_ACTION_MAP ( application ), G_ACTION ( blue_action ) );
/// ***
main_menu = g_menu_new ();
file_menu = g_menu_new();
/// ***
create_item ( file_menu, "WebCam", "app.webcam", "camera-web", NULL, "<CTRL>O" );
/// ***
create_item ( file_menu, "Microphone", "app.microphone", "audio-input-microphone", NULL, "<CTRL>M" );
/// ***
GMenu *submenu = g_menu_new();
create_submenu_item ( file_menu, submenu, "Choose" );
create_item ( submenu, "Red", "app.color", "audio-input-microphone", "red", "<CTRL>R" );
create_item ( submenu, "green", "app.color", "audio-input-microphone", "green", "<CTRL>G" );
create_item ( submenu, "Blue", "app.color", "audio-input-microphone", "blue", "<CTRL>B" );
/// ***
g_menu_insert_submenu ( main_menu, 0, "Preferences", G_MENU_MODEL ( file_menu ) );
/// ***
gtk_application_set_menubar ( application, G_MENU_MODEL ( main_menu ) );
g_object_unref ( main_menu );
}
static void activate ( GtkApplication *app )
{
GtkWidget *window;
window = gtk_application_window_new ( app );
gtk_window_set_application ( GTK_WINDOW ( window ), GTK_APPLICATION ( app ) );
gtk_window_set_title ( GTK_WINDOW ( window ), "Hello GNOME" );
gtk_widget_show_all ( GTK_WIDGET ( window ) );
}
int main ( int argc, char **argv )
{
GtkApplication *app;
int status;
app = gtk_application_new ( "org.gtk.example", G_APPLICATION_FLAGS_NONE );
g_signal_connect_swapped ( app, "startup", G_CALLBACK ( startup ), app );
g_signal_connect_swapped ( app, "activate", G_CALLBACK ( activate ), app );
status = g_application_run ( G_APPLICATION ( app ), argc, argv );
g_object_unref ( app );
return status;
}
in the case of the following code:
GVariant *state_color;
state_color = g_variant_new_string ( "green" );
color_action = g_simple_action_new_stateful ( "color", G_VARIANT_TYPE_STRING, state_color );
Passing G_VARIANT_TYPE_STRING
works fine.