After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 705655 - Add GSimpleToggleAction and GSimpleRadioAction?
Add GSimpleToggleAction and GSimpleRadioAction?
Status: RESOLVED DUPLICATE of bug 667973
Product: glib
Classification: Platform
Component: gapplication
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2013-08-08 07:59 UTC by Murray Cumming
Modified: 2017-02-12 14:46 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Murray Cumming 2013-08-08 07:59:16 UTC
GSimpleAction is overly generic, which makes it hard to see how to implement toggle actions and radio actions, and it involves separate concepts (state, parameter, target) that are sometimes nearly-equivalent in these cases and therefore confuse the API in those cases.


Toggle actions:

Currently it's meant to be done like this, or at least that's what works for me:
* Create it with:
  g_simple_action_new_stateful("somename", NULL, g_variant_new_boolean(FALSE))
* Handle its "activate" signal,
  ignoring its GVariant* "parameter" parameter,
  using g_action_get_state() to get the GVariant* and then g_variant_get_boolean() on that,
  then actually toggle the action by calling g_action_change_state()
  with g_variant_new_boolean(!thatbool),
  the actually respond to the toggle.

Ideally, GSimpleToggleAction would change the state automatically, at least by default, because that is the common case, and what has worked well enough with GtkToggleAction. It would be nice for it to have API like this:
* g_simple_toggle_action_new(const char* name, gboolean initial_state)
* g_simple_toggle_action_get_bool_state()
  (This can't be get_state() because that exists in the base GSimpleAction and overriding just a return type is discouraged in OOP.).
* A "toggled" signal that passes just a gboolean parameter, and that (by default at least) automatically changes the state so the application code doesn't have to.


Radio actions:

Currently it's meant to be done like this, or at least that's what works for me:
* Create it with:
  g_simple_action_new_stateful("somename", G_VARIANT_TYPE_STRING, g_variant_new_string("initialstate"));
  Other types such as G_VARIANT_TYPE_INT can be used, but GSimpleRadioAction  should probably stick to making it easy to use just one type. The parameter type and initial state type must match, so GSimpleRadioAction should avoid the need to specify the parameter type at all, as that is superfluous.

* Handle its "activate" signal,
  using its GVariant* "parameter" parameter (unlike with a toggle item),
  but don't use g_action_get_state() (unlike with a toggle item),
  using g_variant_get_string() (or whatever) on that,
  then actually select the radio item by calling g_action_change_state()
  passing exactly the same GVariant* that the signal has provided as the "parameter",
  then actually respond to the selection of the radio item.

Again, ideally GSimpleRadioAction would change the state automatially, at least by default. It would be nice for it to have API like this:
* g_simple_radio_action_new(const char* name, const char* initial_state)
* g_simple_radio_action_get_string_state()
  (This can't be get_state() because that exists in the base GSimpleAction and overriding just a return type is discouraged in OOP.).
* A "selected" signal that passes just a const char* parameter, and that (by default at least) automatically changes the state so the application code doesn't have to.

Not that an enum-based radio action would probably be better than a string-based one, so we could maybe have GSimpleRadioEnumAction. See bug #705483 .
Comment 1 Murray Cumming 2013-09-16 11:17:08 UTC

*** This bug has been marked as a duplicate of bug 667973 ***
Comment 2 Daniel Boles 2017-02-12 14:42:51 UTC
Sorry for the bump, but this is linked in the hg file, so it seems worth elaborating on for posterity.

(In reply to Murray Cumming from comment #0)
> GSimpleAction is overly generic, which makes it hard to see how to implement
> toggle actions and radio actions, and it involves separate concepts (state,
> parameter, target) that are sometimes nearly-equivalent in these cases and
> therefore confuse the API in those cases.

Agreed. Having said that:

> Toggle actions:
> 
> Currently it's meant to be done like this, or at least that's what works for
> me:
> * Create it with:
>   g_simple_action_new_stateful("somename", NULL,
> g_variant_new_boolean(FALSE))
> * Handle its "activate" signal,
>   ignoring its GVariant* "parameter" parameter,
>   using g_action_get_state() to get the GVariant* and then
> g_variant_get_boolean() on that,
>   then actually toggle the action by calling g_action_change_state()
>   with g_variant_new_boolean(!thatbool),
>   the actually respond to the toggle.

The way it works in GIO, as of 2.40+, is as follows

 * If unconnected, signal activate toggles for us and forwards to change-state.
 * If unconnected, signal change-state forwards to set_state().

So I find that the nicer way to handle this is:

 * Connect to signal change-state
 * The received Variant is the requested state, computed by signal activate
 * Decide whether that change is currently allowed. If not, return early
 * If yes, then apply your response to the new state ( e.g. frobnicate(state) )
 * ...and finally call set_state() yourself to apply it on the action.

This is complicated in giomm because set_state() was moved to protected access. Kjell approved my patch to make this public in master, but it's still a question mark for 2.50, so currently we need to go down into the C API to apply this pattern (which I do, but I tend to think any gobj() and const_cast is too much).

Ultimately, it's still probably less convenient than it could be, but I think this way is (or would be, if set_state() worked) _less_ hassle than the above.
Comment 3 Daniel Boles 2017-02-12 14:46:48 UTC
(In reply to Daniel Boles from comment #2)
> This is complicated in giomm because set_state() was moved to protected
> access. Kjell approved my patch to make this public in master, but it's
> still a question mark for 2.50, so currently we need to go down into the C
> API to apply this pattern (which I do, but I tend to think any gobj() and
> const_cast is too much).

I should link the bug for that: https://bugzilla.gnome.org/show_bug.cgi?id=777953