Ubuntu – How to use accelerators in Gtk

application-developmentgtkvala

I need to make an application in Vala, using Gtk, that supports keyboard accelerators that can be changed by the user.

First, I add an entry to the global Gtk.AccelMap and then set the accel_path for the Gtk.MenuItems. But, it doesn't work. The accels don't appear in the items of the menubar.
To clear what I'm trying to do, here is a sample code:

// main.vala
public class MyWindow: Gtk.Window {
    public MyWindow() {
    this.set_default_size(500, 500);

    var main_box = new Gtk.VBox(false, 0);
    this.add(main_box);

    // Menubar
    var menubar = new Gtk.MenuBar();
    main_box.pack_start(menubar, false, false, 0);

    var file = new Gtk.MenuItem.with_label("File");
    menubar.add(file);

    var file_menu = new Gtk.Menu();
    file.set_submenu(file_menu);

    var quit_mi = new Gtk.MenuItem.with_label("Quit");
    file_menu.append(quit_mi);

    // Register a new accelerator with the global accelerator map
    Gtk.AccelMap.add_entry("<MyWindow>/File/Quit", 'Q', Gdk.ModifierType.CONTROL_MASK);
    quit_mi.set_accel_path("<MyWindow>/File/Quit");

    // Connect signals
    quit_mi.activate.connect(Gtk.main_quit);

    // Label
    var label = new Gtk.Label("My Window");
    main_box.pack_start(label, true, true, 0);

    this.destroy.connect(Gtk.main_quit);
    }
}

int main(string[] args) {
    Gtk.init(ref args);

    var win = new MyWindow();
    win.show_all();

    Gtk.main();
    return 0;
}

I use:

valac main.vala -o main --pkg gtk+-3.0

to compile the source code.

So, the question is: what's missing in the code? I think I need to do something else, but I don't know what.

Best Answer

Could you please clarify whether you want mnemonics (keyboard shortcuts for gui widgets i.e. ctrl-q) or accelerators (keyboard shortcuts for activating menu items i.e. alt-f q). As far as I understand these are two different things, so setting a mnemonic for a menu item will not also form a accelerator for it.

In any case, for the accelerators you can form them by simply creating your menu items with a different function: Gtk.MenuItem.with_mnemonic("_File"); in stead of Gtk.MenuItem.with_label("File"). It is then re-definable with e.g. the file.set_label('Fil_e') function

For the mnemonics, I'm not exactly sure why it doesn't work, as I'm totally new to vala. But I was able to piggy bag of of this c-example and get it to work using accelerator groups in stead of the accelerator map. So I replaced

// Register a new accelerator with the global accelerator map
Gtk.AccelMap.add_entry("<MyWindow>/File/Quit", 'Q', Gdk.ModifierType.CONTROL_MASK);
quit_mi.set_accel_path("<MyWindow>/File/Quit");enter code here

with

var accel_group = new Gtk.AccelGroup();
this.add_accel_group(accel_group);
quit_mi.add_accelerator("activate", accel_group, 'R', Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE);

and that seems to do the trick.

I hope it helps. Regards TLE

Related Question