How to listen for array changes in GSettings?

In my GSettings I have the following key:

<key name="shifter-quote" type="ai">

I need to connect a signal handler to monitor for changes in that array
but I’m getting a core dump when emitting a changed signal:

g_signal_connect(settings, "changed::shifter-quote", callback, NULL);
g_signal_emit_by_name(settings, "changed::shifter-quote", NULL);

How am I supposed to listen for array changes?

You most definitely cannot emit the changed signal yourself. The only signals you can emit by yourself are signals with the G_SIGNAL_ACTION flag; any other signal is emitted by the class that defines them, or is not emitted at all.

In the same way you’re supposed to listen to any other value change on a key: either by calling g_setting_set(), or because some other process is calling g_setting_set() on the same key you’re monitoring.

I used a public API to emit a public signal, and there is nothing that suggests me that I can’t: why on earth are you surprised? I would be surprised by the core dump, not by the fact that I’m trying to emit a signal.

I don’t understand that: with “listening” I mean to call my callback whenever any of the elements in the array changes, so the real question was: g_signal_connect(settings, "changed::array-setting", callback, NULL) is the right way to listen for changes on array settings?

The signal emission, that I given for granted, was added to refresh the UI at the start (the callback updates some widgets).

Of course the API is public: how would you be able to implement a type, otherwise? The fact that g_signal_emit() is public does not imply that you’re free to go around emitting signals on random classes. You cannot emit random signals yourself: only the class that defines the signal can emit it. The only exception to that rule is for signals defined with a G_SIGNAL_ACTION flag.

I honestly don’t understand what you’re trying to achieve, here.

GSettings is a storage API: you store values into it. The change notification is useful if something other than your own code changes those values. For instance, if those settings are part of a system component, and you’re writing a UI to monitor those changes.

If you’re already setting the array then you can update the UI in the very same place; as soon as you call g_settings_set() (or one of its wrappers) the settings instance will dump those values into the settings storage, which will then emit a notification that the settings have been changed. The only caveat is that you need to connect to the changed signal and you retrieved the value of the key after connecting to the signal.

And this is exactly my use case: my code is not the only one changing that array.

The snippets I posted are a simplification: I used to emit “changed” signals just for convenience… I did not even think that could be a problem. As a side note, it works as expected for every scalar setting but the array.

Regardling my original question, and seeing you are not raising any objection, I suppose that g_signal_connect(settings, "changed::array-setting", callback, NULL) should work.

Why the g_signal_emit functions do not check the flag of a signal in order to prevent emitting “wrong” signals? For the own purpose, the API makers can introduce private versions of signal-emitting functions.

I have asked this question because I also was confronted with situations where it was not obvious that my use of API functions was not conform with the ideas of API makers how it should be.

You’ll find the info about it in the description of signal flags (enum GSignalFlags):
G_SIGNAL_ACTION Action signals are signals that may freely be emitted on alive objects from user code via g_signal_emit() and friends, without the need of being embedded into extra code that performs pre or post emission adjustments on the object. They can also be thought of as object methods which can be called generically by third-party code.” (Signals: GObject Reference Manual)

The other side of this info means that you should not emit other signals. Sometimes it seems to work and sometimes not. However I think that the documentation, in general, is not always helpful by preventing the wrong usage of API.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.