How can I switch between two menu bars occupying the same space below the window title in GTK3?

176 views Asked by At

I like to switch menu bars depending on a button or internal state (COM port used). How can I do that in GTK3+ (preferably using Glade and GtkBuilder)? GtkOverlay does not seem to be the correct approach.

2

There are 2 answers

0
jcoppens On

Put both menubars in a gtk(v)box and just declare one of the menubars as invisible in Glade (Leave the one you want by default visible). Then you can later switch menubars by hiding/showing them.

Mind, if you are on Ubuntu, you might run into problems. Ubuntu's Unity moves the menu bar to the top of the workspace, and it might not be happy with two menu bars just existing. In a program I made a couple of years ago Ubuntu refused to show the second menu (but I wasn't hiding either of them, so you might be in luck).

1
Günter Fuchs On

Thanks jcoppens for your answer, but I am not sure how the solution would look over all with one of the positions in the vertical box invisible but still occupying space / the height of one menu bar. Wouldn't that create a gap between either the title and the menu bar (first menu bar visible) or the menu bar and the container below (second menu bar visible)?

I solved it by (before I saw your answer):

  • Using Glade, create a new file and put the two menu bars in there.
  • In the Glade file for the main window, create a vertical box with one item right below the title. (In my case, my main frame contains a vertical box with three items, the first position is kept empty and will contain one of the two menu bars, the second one contains all other items inside another container, and the third item contains a status bar.)
  • In the C module using GtkBuilder, I switch the menu bars as shown below:


    /**
     * This function adds or replaces the menu bar.
     * @param id id string for menu bar
     */
        void amci_tester_set_menubar(const gchar *id) {
            GtkWidget *menu_bar = GTK_WIDGET(gtk_builder_get_object(builder, id));
            GtkBox *box_menu = GTK_BOX(gtk_builder_get_object(builder, "boxMainMenu"));
            GList *children = gtk_container_get_children(GTK_CONTAINER(box_menu));
            if (children != NULL)
                gtk_container_remove(GTK_CONTAINER(box_menu), (GtkWidget *) g_list_first(children)->data);
            gtk_box_pack_start(box_menu, menu_bar, false, false, 0);
            // Although the visible property is shown as being set in the Glade GUI, in
            // the Glade file it is not set.
            gtk_widget_set_visible(menu_bar, true);
            g_list_free(children);
        }

In the beginning of main, I put the usual GtkBuilder stuff, instantiating a GtkBuilder object and then adding the default / first to be shown menu bar object:

// Init GTK+.
gtk_init(&argc, &argv);

// Create new GtkBuilder object from file.
builder = gtk_builder_new_from_file(glade_filename_app);
if (builder == NULL) {
    g_warning("Could not create builder from %s", glade_filename_app);
    return 1;
}
// Add menu bar for PC menu bar (default) from file.
if (!gtk_builder_add_from_file(builder, glade_filename_menu_pc, &error))    {
    g_warning("%s", error->message);
    g_free(error);
    return 1;
}