Gtk4 model-backed radio button in Python

Sat, 29 Apr 2023 14:03:06 -0000
pdo, python, eng, gtk

Gtk4 has interesting ways of splitting models and views. One that I didn't find very well documented, especially for Python bindings, is a set of radio buttons backed by a common model.

The idea is to define an action that takes a string as a state. Each radio button is assigned a string matching one of the possible states, and when the state of the backend action is changed, the radio buttons are automatically updated.

All the examples below use a string for a value type, but anything can be used that fits into a GLib.Variant.

The model

This defines the action. Note that enables all the usual declarative ways of a status change:

mode = Gio.SimpleAction.new_stateful(
        name="mode-selection",
        parameter_type=GLib.VariantType("s"),
        state=GLib.Variant.new_string(""))
gtk_app.add_action(self.mode)

The view

def add_radio(model: Gio.SimpleAction, id: str, label: str):
    button = Gtk.CheckButton(label=label)

    # Tell this button to activate when the model has the given value
    button.set_action_target_value(GLib.Variant.new_string(id))

    # Build the name under which the action is registesred, plus the state
    # value controlled by this button: clicking the button will set this state
    detailed_name = Gio.Action.print_detailed_name(
            "app." + model.get_name(),
            GLib.Variant.new_string(id))
    button.set_detailed_action_name(detailed_name)

    # If the model has no current value set, this sets the first radio button
    # as selected
    if not model.get_state().get_string():
        model.set_state(GLib.Variant.new_string(id))

Accessing the model

To read the currently selected value:

current = model.get_state().get_string()

To set the currently selected value:

model.set_state(GLib.Variant.new_string(id))