Problem with setting up an Action

I am trying to create an menu with GMenu and at the the Items added to that menu works fine, but the Quit item added inside the Section and latter added to the menu (file_menu) does not seems to work.

discourse

The New and Open actions are working fine and they are clickable, but the Quit is inactive and NOT clickable.

Here is a demo program:

#include <gtk/gtk.h>

static void new_clbk ( GSimpleAction *action, GVariant *parameter, gpointer user_data )
{
    ( void ) action;
    ( void ) parameter;
    ( void ) user_data;
    g_print ( "You clicked New\n" );
}

static void open_clbk ( GSimpleAction *action, GVariant *parameter, gpointer user_data )
{
    ( void ) action;
    ( void ) parameter;
    ( void ) user_data;
    g_print ( "You clicked Open\n" );
}

static void quit_clbk ( GSimpleAction *action, GVariant *parameter, gpointer user_data )
{
    ( void ) action;
    ( void ) parameter;
    ( void ) user_data;
    g_print ( "You clicked Quit\n" );
}

static void create_menu_item ( GMenu *menu,
                               const gchar *const label,
                               const gchar *const detailed_action,
                               const gchar *const accel )
{
    GMenuItem *item;
    item = g_menu_item_new ( label, detailed_action );

    if ( accel )
    {
        g_menu_item_set_attribute ( item, "accel", "s", accel, NULL );
    }

    g_menu_append_item ( menu, item );
    g_object_unref ( item );
}

static void create_file_menu ( GMenu *menu, const gchar *const label )
{
    GMenu *section;
    GMenu *file_menu;

    section   = g_menu_new();
    file_menu = g_menu_new ();

    /// *** Create the File Menu
    create_menu_item ( file_menu, "New",  "app.new",  "<CTRL>N" );
    create_menu_item ( file_menu, "Open", "app.open", "<CTRL>O" );

    /// *** Create the Section
    create_menu_item ( section,   "quit",  "open.quit", "<CTRL>Q" );
    g_menu_append_section ( file_menu, NULL, G_MENU_MODEL ( section ) );

    ///
    g_menu_insert_submenu ( menu, 0, label,  G_MENU_MODEL ( file_menu ) );
    g_object_unref ( file_menu );
    g_object_unref ( section );
}

static void startup ( GtkApplication *application )
{
    static const GActionEntry actions[] =
    {
        { "new",  new_clbk,  NULL, NULL, NULL, { 0, 0, 0 } },
        { "open", open_clbk, NULL, NULL, NULL, { 0, 0, 0 } },
        { "quit", quit_clbk, NULL, NULL, NULL, { 0, 0, 0 } },
    };

    GMenu *main_menu;

    /// ***
    g_action_map_add_action_entries ( G_ACTION_MAP ( application ), actions, G_N_ELEMENTS ( actions ), application );

    /// ***
    main_menu = g_menu_new ();

    /// ***
    create_file_menu ( main_menu, "File" );

    /// ***
    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;
}

You put the “quit” action under the “open” action group, but you never created an “open” group. GTK will automatically add the “app” group, for actions added to the GtkApplication; and “win” group, for actions added to a GtkApplicationWindow.

1 Like

OH, I feel so ashamed right now :expressionless:

Don’t worry, happens to literally everyone. :laughing:

Quick note: if you don’t want to use (void) unused_argument a lot, there’s a macro in GLib called G_GNUC_UNUSED that you can use to annotate unused arguments, e.g.:

static void quit_clbk (GSimpleAction *action G_GNUC_UNUSED,
                       GVariant *parameter G_GNUC_UNUSED,
                       gpointer user_data G_GNUC_UNUSED)
{
  // ...
}

This will avoid warnings.

3 Likes

This is definitely a good and useful thing.

Can you mark @ebassi 's answer as Solution ? (Instead of “I feel so ashamed right now”). Because it helps new comers and future visitors (who had similar issue) in knowing the right answer. :sweat_smile:

1 Like

@MichiB FYI, this sounds as a valid solution to me :smiley:

1 Like

LOL, being on phone is not the best thing for things like this one :smiley:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.