How to use GtkToggleButton with actions?

Hello all.
I would like two add two complementary toggle buttons to a group.
Gtk.ToggleButton.set_group says:

Note that the same effect can be achieved via the GtkActionable API, by using the same action with parameter type and state type ‘s’ for all buttons in the group, and giving each button its own target value.

But I’m not able to achieve it. This is what I tried:

import gi

gi.require_versions({"Adw": "1"})
from gi.repository import Adw, Gio, GLib, Gtk


@Gtk.Template(filename="win.ui")
class ExampleWin(Adw.ApplicationWindow):
    __gtype_name__ = "ExampleWin"


def on_activate(application):
    win = ExampleWin(application=application)
    win.set_default_size(400, 500)
    win.present()


switch_pages_action = Gio.SimpleAction(
    name="switch_pages_view",
    state=GLib.Variant("s", "SINGLE"),
    parameter_type=GLib.VariantType("s"),
    state_type=GLib.VariantType("s"),
)
switch_pages_action.connect("activate", lambda *s: print("Switch", s))

app = Adw.Application(application_id="com.example.app")
app.add_action(switch_pages_action)
app.connect("activate", on_activate)
app.run([])

win.ui

<?xml version='1.0' encoding='utf-8'?>
<!-- Created with Cambalache 0.10.3 -->
<interface>
  <!-- interface-name win -->
  <requires lib="gtk" version="4.6" />
  <requires lib="libadwaita" version="1.1" />
  <menu id="main_menu">
    <section>
      <item>
        <attribute name='label' translatable='yes'>Pages View</attribute>
        <attribute name='custom'>pages_view</attribute>
      </item>
    </section>
  </menu>
  <template class="ExampleWin" parent="AdwApplicationWindow">
    <child>
      <object class="GtkBox">
        <property name="halign">center</property>
        <property name="valign">center</property>
        <child>
          <object class="GtkMenuButton">
            <property name="popover">
              <object class="GtkPopoverMenu" id="popover">
                <property name="menu-model">main_menu</property>
                <child type="pages_view">
                  <object class="GtkBox">
                    <child>
                      <object class="GtkToggleButton">
                        <property name="action-name">app.switch_pages_view</property>
                        <property name="action-target">SINGLE</property>
                        <property name="icon-name">view-continuous-symbolic</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkToggleButton">
                        <property name="action-name">app.switch_pages_view</property>
                        <property name="action-target">DUAL</property>
                        <property name="active">True</property>
                        <property name="icon-name">view-dual-symbolic</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </property>
          </object>
        </child>
      </object>
    </child>
  </template>
</interface>

When I run it (python3 -m app), I get these warnings.

/home/arun-mani-j/Projects/web/app.py:18: Warning: g_object_new_is_valid_property: property 'state-type' of object class 'GSimpleAction' is not writable
  switch_pages_action = Gio.SimpleAction(

(python3:29760): Gtk-WARNING **: 01:00:28.623: Failed to set property GtkToggleButton.action-target to SINGLE: 0:expected value

(python3:29760): Gtk-WARNING **: 01:00:28.623: Failed to set property GtkToggleButton.action-target to DUAL: 0:expected value

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

(python3:29760): Gtk-WARNING **: 01:00:28.623: actionhelper: action app.switch_pages_view can't be activated due to parameter type mismatch (parameter type s, target type NULL)

How to add these buttons to a group such that their values are complement of each other?

Thanks for reading. :upside_down_face:

The action-target property is actually a GVariant text string that can support arbitrary data similar to JSON, so you must quote the string value:

Then if you remove that connect("activate", ...) to use the default handler, it should work. For stateful actions you probably want to connect to change-state, and you will have to call set_state manually if overriding the default handler.

1 Like

Thanks a lot! It is working good now :smiley:

Here is the full working example for future readers.

app.py

import gi

gi.require_versions({"Adw": "1"})
from gi.repository import Adw, Gio, GLib, Gtk


@Gtk.Template(filename="win.ui")
class ExampleWin(Adw.ApplicationWindow):
    __gtype_name__ = "ExampleWin"


def on_activate(application):
    win = ExampleWin(application=application)
    win.set_default_size(400, 500)
    win.present()


switch_pages_action = Gio.SimpleAction(
    name="switch_pages_view",
    state=GLib.Variant("s", "DUAL"),
    parameter_type=GLib.VariantType("s"),
)
switch_pages_action.connect("change-state", lambda x, y: x.set_state(y))

app = Adw.Application(application_id="com.example.app")
app.add_action(switch_pages_action)
app.connect("activate", on_activate)
app.run([])

win.ui

<?xml version='1.0' encoding='utf-8'?>
<!-- Created with Cambalache 0.10.3 -->
<interface>
  <!-- interface-name win -->
  <requires lib="gtk" version="4.6" />
  <requires lib="libadwaita" version="1.1" />
  <template class="ExampleWin" parent="AdwApplicationWindow">
    <child>
      <object class="GtkBox">
        <property name="halign">center</property>
        <property name="valign">center</property>
        <child>
          <object class="GtkToggleButton">
            <property name="action-name">app.switch_pages_view</property>
            <property name="action-target">'SINGLE'</property>
            <property name="active">False</property>
            <property name="icon-name">view-paged-symbolic</property>
            <property name="css-classes">flat</property>
          </object>
        </child>
        <child>
          <object class="GtkToggleButton">
            <property name="action-name">app.switch_pages_view</property>
            <property name="action-target">'DUAL'</property>
            <property name="active">True</property>
            <property name="icon-name">view-dual-symbolic</property>
            <property name="css-classes">flat</property>
          </object>
        </child>
      </object>
    </child>
  </template>
</interface>