0
votes

I'm trying to connect up an accelerator to a Gtk::ToggleToolButton, unfortunately the "toggle" signal isn't 'activatable' and so you must connect to "clicked" instead like so:

togglebutton->add_accelerator("clicked", ...etc..)

This works, and fires whatever handler is connected to signal_clicked() but, it doesn't actually change the appearance of the button, or fire the "toggled" signal. Basically firing "clicked" doesn't change the "active" state of the button.

So, the obvious solution is to call toolbutton->set_active(true/false) from inside the "clicked" callback. But the problem now is that set_active itself fires the "clicked" signal and the "toggled" signal, so you end up in an infinite loop of:

accelerator -> clicked handler -> set_active() -> clicked handler -> set_active()

So, my question is, how can I add an accelerator to a ToggleToolButton which results in the expected behaviour of toggling the button?

2

2 Answers

2
votes

This works, and fires whatever handler is connected to signal_clicked() but, it doesn't actually change the appearance of the button, or fire the "toggled" signal.

I'm not sure this is correct. The default clicked handler for a ToggleButton appears to result in the toggled signal being fired, and the appearance changing as you'd expect.

But if you manually connect to the clicked signal, and don't chain up to the default handler, then you stop this from happening! Took me a little while to work that out. I'm sure how exactly to go about doing the chain-up in gtkmm (I usually use C or Vala for GTK work), but it doesn't really matter as you can just let the default handler to its thing and connect to toggled like you want to.

This is the test code I used:

#include <gtkmm.h>

void on_toggle()
{
    g_print("Toggled\n");
}

int main(int argc, char **argv)
{
    Gtk::Main kit(argc, argv);

    Gtk::Window w;
    Gtk::ToggleButton t("Click me");

    Glib::RefPtr<Gtk::AccelGroup> group = Gtk::AccelGroup::create();

    t.add_accelerator("clicked", group, GDK_KEY_N, (Gdk::ModifierType) 0,(Gtk::AccelFlags) 0);
    t.signal_toggled().connect(sigc::ptr_fun(&on_toggle));

    w.add_accel_group(group);
    w.set_default_size(100, 100);
    w.add(t);
    w.show_all();

    kit.run(w);

    return 0;
}
2
votes

Mystery solved!

Thanks to @conscioususer on Twitter: https://twitter.com/conscioususer/statuses/396397287288889344

It turns out that Gtk::ToggleToolButton is in fact a ToolButton with a child ToggleButton. The way to make it work is to connect the accelerator to the child widget (e.g. toggletoolbutton->get_child()->add_accelerator("clicked", ...)) and then everything works as expected!