Search code examples
gtkgtk3

Search does not work in GtkShortcutsWindow when not using GtkBuilder


I have created a window that displays shortcuts by using GtkShortcutsWindow. However, I do not want to load an extern .ui file and using gtk_builder_new_from_string requires quite a large string. I came up with a concise solution by creating the necessary objects and pack them into the window and its containers GtkShortcutsSection and GtkShortcutsGroups. The result looks exactly as if I would use gtk_builder_new_from_string (I've tried both approaches), but when not using GtkBuilder the built-in search at the top of the window does not work, showing no results. What am I missing here? Here are the relevant parts of my code:

enum { FILE_HNDL_GRP, EDITING_GRP, FIND_GRP, VIEW_GRP, HELP_GRP, NUMBER_OF_SC_GROUPS };

gchar *accels[] = { "", 
                    "<ctrl>N", "<ctrl>O", "<ctrl>S", "<ctrl><shift>S", "<ctrl>Q", 
                    "", 
                    "<ctrl>A", "<ctrl>backslash", "<ctrl>Z", "<ctrl>Y", "<ctrl>T", 
                    "<ctrl>minus", "<ctrl>plus", "<ctrl>B", "<ctrl>R", "<ctrl><shift>R", 
                    "", 
                    "<ctrl>F", "<ctrl>H", 
                    "", 
                    "<shift><ctrl>X", "<shift><ctrl>C", 
                    "", 
                    "<ctrl>L", "<shift><ctrl>A"
                  };

gchar *accel_txts[] = { "File Handling", 
                            "Create a new menu" , "Open a menu", "Save the menu", 
                            "Save the menu as...", "Quit the application", 
                        "Editing", 
                            "Select all visible nodes", "Deselect all visible nodes", "Undo previous edit", 
                            "Redo previous edit", "Move node to the top", "Move node up", "Move node down", 
                            "Move node to the bottom", "Remove node", "Remove children from node", 
                        "Find", 
                            "Show/Hide Find Grid", "Open/Close\nFind & Replace Window", 
                        "View", 
                            "Expand all nodes", "Collapse all nodes", 
                        "Help", 
                            "Open/Close\nShortcuts Window", "About"
                      };

guint8 number_of_shortcuts = sizeof (accels) / sizeof (accels[0]);

GtkShortcutsWindow *shortcuts_window;
GtkShortcutsSection *shortcuts_section;
GtkShortcutsGroup *shortcuts_groups[NUMBER_OF_SC_GROUPS];

guint8 shortcuts_cnt;
gint8 groups_cnt = -1;

shortcuts_window = g_object_new (GTK_TYPE_SHORTCUTS_WINDOW, "modal", TRUE, 
                                                            "resizable", TRUE, 
                                                            "gravity", GDK_GRAVITY_CENTER, 
                                                             NULL);

shortcuts_section = g_object_new (GTK_TYPE_SHORTCUTS_SECTION, "visible", TRUE, "max-height", 12, NULL);
gtk_container_add (GTK_CONTAINER (shortcuts_window), GTK_WIDGET (shortcuts_section));

for (shortcuts_cnt = 0; shortcuts_cnt < number_of_shortcuts; shortcuts_cnt++) {
    if (!(accels[shortcuts_cnt][0] == '<')) {
        groups_cnt++;
        shortcuts_groups[groups_cnt] = g_object_new (GTK_TYPE_SHORTCUTS_GROUP, "title", accel_txts[shortcuts_cnt], NULL);
        gtk_container_add (GTK_CONTAINER (shortcuts_section), GTK_WIDGET (shortcuts_groups[groups_cnt]));
    }
    else {      
        gtk_container_add (GTK_CONTAINER (shortcuts_groups[groups_cnt]), 
                           GTK_WIDGET (g_object_new (GTK_TYPE_SHORTCUTS_SHORTCUT, 
                                                     "accelerator", accels[shortcuts_cnt], 
                                                     "title", accel_txts[shortcuts_cnt], 
                                                     NULL)));
    }
}

gtk_window_set_transient_for (GTK_WINDOW (shortcuts_window), GTK_WINDOW (window));

gtk_widget_show_all (GTK_WIDGET (shortcuts_window));

Solution

  • I've found the hints how to solve this in GTK's bugzilla. There are two things that have to be changed in the code above:

    1. Sections have to be added to the shortcuts window only AFTER the shortcut groups have been added to them.
    2. One of the sections has to be shown BEFORE adding it to the shortcuts window. You can't find this out by yourself by reading the documentation; I had to consult bugzilla for that.

    The following code features two groups with one shortcut each:

    enum { FILE_HNDL_GRP, HELP_GRP, NUMBER_OF_SC_GROUPS };
    
    GtkShortcutsWindow *shortcuts_window;
    GtkShortcutsSection *shortcuts_section;
    GtkShortcutsGroup *shortcuts_groups[NUMBER_OF_SC_GROUPS];
    
    // shortcut_window_elements
    char *sc_win_elm[] = { "File Handling", 
                               "<ctrl>N | Create a new menu", 
                            "Help", 
                                "<shift><ctrl>A | About"
                         };
    
    gchar **tokens;
    guint8 num_of_sc_win_elm = sizeof (sc_win_elm) / sizeof (sc_win_elm[0]); // number_of_shortcut_window_elements
    
    guint8 sc_win_elm_cnt; // shortcut_window_element_counter
    gint8 groups_cnt = -1;
    
    shortcuts_window = g_object_new (GTK_TYPE_SHORTCUTS_WINDOW, "modal", TRUE, 
                                                                "resizable", TRUE, 
                                                                "gravity", GDK_GRAVITY_CENTER, 
                                                                "transient-for", window, 
                                                                NULL);
    
    shortcuts_section = g_object_new (GTK_TYPE_SHORTCUTS_SECTION, "visible", TRUE, "max-height", 12, NULL);
    gtk_widget_show (GTK_WIDGET (shortcuts_section));
    
    // Add shortcut groups and shortcuts.
    
    for (sc_win_elm_cnt = 0; sc_win_elm_cnt < num_of_sc_win_elm; sc_win_elm_cnt++) {
        if (!(strstr (sc_win_elm[sc_win_elm_cnt], "|"))) {       
            groups_cnt++;
            shortcuts_groups[groups_cnt] = g_object_new (GTK_TYPE_SHORTCUTS_GROUP, "title", sc_win_elm[sc_win_elm_cnt], NULL);
            gtk_container_add (GTK_CONTAINER (shortcuts_section), GTK_WIDGET (shortcuts_groups[groups_cnt]));
        }
        else {
            enum { ACCEL, ACCEL_TXT };
            tokens = g_strsplit (sc_win_elm[sc_win_elm_cnt], " | ", -1);
    
            gtk_container_add (GTK_CONTAINER (shortcuts_groups[groups_cnt]), 
                               GTK_WIDGET (g_object_new (GTK_TYPE_SHORTCUTS_SHORTCUT, 
                                                         "accelerator", tokens[ACCEL], 
                                                         "title", tokens[ACCEL_TXT], 
                                                         NULL)));
    
            g_strfreev (tokens);
        }
    }
    
    gtk_container_add (GTK_CONTAINER (shortcuts_window), GTK_WIDGET (shortcuts_section)); 
    
    gtk_widget_show_all (GTK_WIDGET (shortcuts_window));