/* Copyright (C) 2010 Jonathon Jongsma
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*/
_CONFIGINCLUDE(giommconfig.h)
#include
#include
#include
_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)
namespace Gio
{
class GIOMM_API SettingsSchema;
/** A high-level API for application settings
*
* The Settings class provides a convenient API for storing and retrieving
* application settings.
*
* @newin{2,28}
*/
class GIOMM_API Settings : public Glib::Object
{
_CLASS_GOBJECT(Settings, GSettings, G_SETTINGS, Glib::Object, GObject, , , GIOMM_API)
public:
_WRAP_ENUM(BindFlags, GSettingsBindFlags, decl_prefix GIOMM_API)
protected:
_WRAP_CTOR(Settings(const Glib::ustring& schema_id), g_settings_new)
_WRAP_CTOR(Settings(const Glib::ustring& schema_id, const Glib::ustring& path), g_settings_new_with_path)
//TODO: Requires SettingsBackend: _WRAP_CTOR(Settings(const Glib::ustring& schema_id, const Glib::RefPtr& backend), g_settings_new_with_backend)
//TODO: Requires SettingsBackend: _WRAP_CTOR(Settings(const Glib::ustring& schema_id, const Glib::RefPtr& backend, const Glib::ustring& path), g_settings_new_with_backend_and_path)
//TODO: Requires SettingsBackend: _WRAP_CTOR(Settings(const Glib::RefPtr& settings_schema, const Glib::RefPtr& backend, const Glib::ustring& path), g_settings_new_full)
public:
_WRAP_CREATE(const Glib::ustring& schema_id)
_WRAP_CREATE(const Glib::ustring& schema_id, const Glib::ustring& path)
//TODO: Requires SettingsBackend: _WRAP_CREATE(const Glib::ustring& schema_id, const Glib::RefPtr& backend)
//TODO: Requires SettingsBackend: _WRAP_CREATE(const Glib::ustring& schema_id, const Glib::RefPtr& backend, const Glib::ustring& path)
//TODO: Requires SettingsBackend: _WRAP_CREATE(const Glib::RefPtr& settings_schema, const Glib::RefPtr& backend, const Glib::ustring& path)
//TODO: Rename these to get/set_*_value_variant() and add templated get/set_*_value() methods as elsewhere?
_WRAP_METHOD(bool set_value(const Glib::ustring& key, const Glib::VariantBase& value), g_settings_set_value)
/** Gets the value that is stored in the settings for a @a key.
*
* It is a programmer error to give a @a key that isn't contained in the
* schema for the settings.
*
* @param key The key to get the value for.
* @param value A Variant of the expected type.
*
* @newin{2,28}
*/
void get_value(const Glib::ustring& key, Glib::VariantBase& value) const;
_IGNORE(g_settings_get_value)
//TODO: We've added a bool return to handle the nullptr return value case,
//but maybe other get_value() methods can return nullptrs too.
/** Checks the "user value" of a @a key, if there is one.
*
* The user value of a key is the last value that was set by the user.
*
* After calling reset() this function should always return
* false (assuming something is not wrong with the system
* configuration).
*
* It is possible that get_value() will return a different
* value than this method. This can happen in the case that the user
* set a value for a key that was subsequently locked down by the system
* administrator -- this method will return the user's old value.
*
* This method may be useful for adding a "reset" option to a UI or
* for providing indication that a particular value has been changed.
*
* It is a programmer error to give a @a key that isn't contained in the
* schema for the settings.
*
* @param key The key to get the user value for.
* @param value A Variant of the expected type.
* @result true if a user value was found.
*
* @newin{2,40}
*/
bool get_user_value(const Glib::ustring& key, Glib::VariantBase& value) const;
_IGNORE(g_settings_get_user_value)
/** Gets the "default value" of a key.
*
* This is the value that would be read if reset() were to be
* called on the key.
*
* Note that this may be a different value than returned by
* get_default_value() if the system administrator
* has provided a default value.
*
* Comparing the return values of get_default_value() and
* value() is not sufficient for determining if a value
* has been set because the user may have explicitly set the value to
* something that happens to be equal to the default. The difference
* here is that if the default changes in the future, the user's key
* will still be set.
*
* This method may be useful for adding an indication to a UI of what
* the default value was before the user set it.
*
* It is a programmer error to give a @a key that isn't contained in the
* schema for the settings.
*
* @param key The key to get the default value for.
* @param value A Variant of the expected type.
*
* @newin{2,40}
*/
void get_default_value(const Glib::ustring& key, Glib::VariantBase& value) const;
_IGNORE(g_settings_get_default_value)
_WRAP_METHOD(int get_int(const Glib::ustring& key) const, g_settings_get_int)
_WRAP_METHOD(bool set_int(const Glib::ustring& key, int value), g_settings_set_int)
_WRAP_METHOD(gint64 get_int64(const Glib::ustring& key) const, g_settings_get_int64)
_WRAP_METHOD(bool set_int64(const Glib::ustring& key, gint64 value), g_settings_set_int64)
_WRAP_METHOD(guint get_uint(const Glib::ustring& key) const, g_settings_get_uint)
_WRAP_METHOD(bool set_uint(const Glib::ustring& key, guint value), g_settings_set_uint)
_WRAP_METHOD(guint64 get_uint64(const Glib::ustring& key) const, g_settings_get_uint64)
_WRAP_METHOD(bool set_uint64(const Glib::ustring& key, guint64 value), g_settings_set_uint64)
_WRAP_METHOD(bool get_boolean(const Glib::ustring& key) const, g_settings_get_boolean)
_WRAP_METHOD(bool set_boolean(const Glib::ustring& key, bool value), g_settings_set_boolean)
_WRAP_METHOD(Glib::ustring get_string(const Glib::ustring& key) const, g_settings_get_string)
_WRAP_METHOD(bool set_string(const Glib::ustring& key, const Glib::ustring& value), g_settings_set_string)
_WRAP_METHOD(double get_double(const Glib::ustring& key) const, g_settings_get_double)
_WRAP_METHOD(bool set_double(const Glib::ustring& key, double value), g_settings_set_double)
#m4 _CONVERSION(`gchar**',`std::vector',`Glib::ArrayHandler::array_to_vector($3, Glib::OWNERSHIP_DEEP)')
_WRAP_METHOD(std::vector get_string_array(const Glib::ustring& key) const, g_settings_get_strv)
_WRAP_METHOD(bool set_string_array(const Glib::ustring& key, const std::vector& value), g_settings_set_strv)
_WRAP_METHOD(int get_enum(const Glib::ustring& key) const, g_settings_get_enum)
_WRAP_METHOD(bool set_enum(const Glib::ustring& key, int value), g_settings_set_enum)
_WRAP_METHOD(guint get_flags(const Glib::ustring& key) const, g_settings_get_flags)
_WRAP_METHOD(bool set_flags(const Glib::ustring& key, guint value), g_settings_set_flags)
// Ignore varargs functions.
_IGNORE(g_settings_get, g_settings_set)
_WRAP_METHOD(Glib::RefPtr get_child(const Glib::ustring& name), g_settings_get_child)
_WRAP_METHOD(Glib::RefPtr get_child(const Glib::ustring& name) const, g_settings_get_child, constversion)
_WRAP_METHOD(bool is_writable(const Glib::ustring& name) const, g_settings_is_writable)
_WRAP_METHOD(void delay(), g_settings_delay)
_WRAP_METHOD(void apply(), g_settings_apply)
_WRAP_METHOD(void revert(), g_settings_revert)
_WRAP_METHOD(bool get_has_unapplied() const, g_settings_get_has_unapplied)
_WRAP_METHOD(void reset(const Glib::ustring& key), g_settings_reset)
#m4 _CONVERSION(`gchar**',`std::vector',`Glib::ArrayHandler::array_to_vector($3, Glib::OWNERSHIP_DEEP)')
_WRAP_METHOD(std::vector list_children() const, g_settings_list_children)
_IGNORE(g_settings_list_keys)
_IGNORE(g_settings_get_range, g_settings_list_relocatable_schemas) dnl// deprecated
_IGNORE(g_settings_range_check)
#m4 _CONVERSION(`Glib::ObjectBase*',`gpointer',(gpointer)$3->gobj())
_WRAP_METHOD(void bind(const Glib::ustring& key, Glib::ObjectBase* object, const Glib::ustring& property, BindFlags flags = BindFlags::DEFAULT), g_settings_bind)
/** Create a binding between the @a key in the @a settings object
* and the @a property_proxy.
*
* The binding uses the default GIO mapping functions to map
* between the settings and property values. These functions
* handle booleans, numeric types and string types in a
* straightforward way. Use g_settings_bind_with_mapping() if
* you need a custom mapping, or map between types that are not
* supported by the default mapping functions.
*
* Unless the @a flags include Gio::Settings::BindFlags::NO_SENSITIVITY, this
* function also establishes a binding between the writability of
* @a key and the "sensitive" property of @a object (if @a object has
* a boolean property by that name). See bind_writable()
* for more details about writable bindings.
*
* Note that the lifecycle of the binding is tied to @a object,
* and that you can have only one binding per object property.
* If you bind the same property twice on the same object, the second
* binding overrides the first one.
*
* @param key The key to bind.
* @param property_proxy The property to bind.
* @param flags Flags for the binding.
*/
void bind(const Glib::ustring& key, const Glib::PropertyProxy_Base& property_proxy, BindFlags flags = BindFlags::DEFAULT);
/** A slot to be called to map values in a binding.
*
* For instance:
* @code
* std::optional map_ustring_to_int(const Glib::ustring& from_string);
* @endcode
*
* @return A value of type T_to if the mapping was successful,
* and an empty optional with no value (i.e. std::nullopt) otherwise.
*/
template
using SlotTypedMapping = sigc::slot(const T_from&)>;
// Gio::Settings::bind() is similar to Glib::Binding::bind_property().
/** Create a binding between the @a key in the @a settings object
* and the property @a property of @a object.
*
* The binding uses the provided mapping functions to map between
* settings and property values.
*
* Note that the lifecycle of the binding is tied to @a object,
* and that you can have only one binding per object property.
* If you bind the same property twice on the same object, the second
* binding overrides the first one.
*
* The template parameters T_setting and T_property must be
* explicitly specified in each call. The compiler can't deduce them.
* For instance:
* @code
* m_settings->bind("transition",
* m_transition, "selected", Gio::Settings::BindFlags::DEFAULT,
* sigc::mem_fun(*this, &ExampleAppPrefs::map_from_ustring_to_int),
* sigc::mem_fun(*this, &ExampleAppPrefs::map_from_int_to_ustring));
* @endcode
*
* @newin{2,76}
*
* @param key The key to bind.
* @param object A Glib::ObjectBase.
* @param property The name of the property to bind.
* @param flags Flags for the binding.
* @param slot_get_mapping A function that gets called to convert values from
* setting to parameter, or an empty slot to use the default GIO mapping.
* @param slot_set_mapping A function that gets called to convert values from
* parameter to setting, or an empty slot to use the default GIO mapping.
*
* @tparam T_setting Type of the setting. Must be a type that can be
* stored in a Glib::Variant object.
* @tparam T_property Type of the property. Must be a type that can be
* stored in a Glib::Value object.
*/
template
void bind(const Glib::ustring& key,
Glib::ObjectBase* object, const Glib::ustring& property, BindFlags flags,
const SlotTypedMapping& slot_get_mapping,
const SlotTypedMapping& slot_set_mapping)
{
return bind_value(key, object, property, flags,
slot_get_mapping.empty() ? SlotGetMapping() : GetMappingProp(slot_get_mapping),
slot_set_mapping.empty() ? SlotSetMapping() : SetMappingProp(slot_set_mapping));
}
/** Create a binding between the @a key in the @a settings object
* and the @a property_proxy.
*
* The binding uses the provided mapping functions to map between
* settings and property values.
*
* Note that the lifecycle of the binding is tied to @a property_proxy's
* object, and that you can have only one binding per object property.
* If you bind the same property twice on the same object, the second
* binding overrides the first one.
*
* The template parameters T_setting and T_property must be
* explicitly specified in each call. The compiler can't deduce them.
* For instance:
* @code
* m_settings->bind("transition",
* m_transition->property_selected(), Gio::Settings::BindFlags::DEFAULT,
* sigc::mem_fun(*this, &ExampleAppPrefs::map_from_ustring_to_int),
* sigc::mem_fun(*this, &ExampleAppPrefs::map_from_int_to_ustring));
* @endcode
*
* @newin{2,76}
*
* @param key The key to bind.
* @param property_proxy The property to bind.
* @param flags Flags for the binding.
* @param slot_get_mapping A function that gets called to convert values from
* setting to parameter, or an empty slot to use the default GIO mapping.
* @param slot_set_mapping A function that gets called to convert values from
* parameter to setting, or an empty slot to use the default GIO mapping.
*
* @tparam T_setting Type of the setting. Must be a type that can be
* stored in a Glib::Variant object.
* @tparam T_property Type of the property. Must be a type that can be
* stored in a Glib::Value object.
*/
template
void bind(const Glib::ustring& key,
const Glib::PropertyProxy_Base& property_proxy, BindFlags flags,
const SlotTypedMapping& slot_get_mapping,
const SlotTypedMapping& slot_set_mapping)
{
bind(key, property_proxy.get_object(),
property_proxy.get_name(), flags, slot_get_mapping, slot_set_mapping);
}
_IGNORE(g_settings_bind_with_mapping)
_WRAP_METHOD(void bind_writable(const Glib::ustring& key, Glib::ObjectBase* object, const Glib::ustring& property, bool inverted=false), g_settings_bind_writable)
/** Create a binding between the writability of @a key in the
* @a settings object and the @a property_proxy.
*
* The property must be boolean; "sensitive" or "visible"
* properties of widgets are the most likely candidates.
*
* Writable bindings are always uni-directional; changes of the
* writability of the setting will be propagated to the object
* property, not the other way.
*
* When the @a inverted argument is true, the binding inverts the
* value as it passes from the setting to the object, i.e. the property
* will be set to true if the key is not writable.
*
* Note that the lifecycle of the binding is tied to @a object,
* and that you can have only one binding per object property.
* If you bind the same property twice on the same object, the second
* binding overrides the first one.
*
* @param key The key to bind.
* @param property_proxy The boolean property to bind.
* @param inverted Whether to 'invert' the value.
*/
void bind_writable(const Glib::ustring& key, const Glib::PropertyProxy_Base& property_proxy, bool inverted=false);
_WRAP_METHOD(static void unbind(Glib::ObjectBase* object, const Glib::ustring& property),
g_settings_unbind, newin "2,76")
/** Removes an existing binding for @a property_proxy.
*
* Note that bindings are automatically removed when the
* object is finalized, so it is rarely necessary to call this
* function.
*
* @newin{2,76}
*
* @param property_proxy The property whose binding is removed.
*/
static void unbind(const Glib::PropertyProxy_Base& property_proxy);
_WRAP_METHOD(Glib::RefPtr create_action(const Glib::ustring& key), g_settings_create_action)
//TODO?: _WRAP_PROPERTY("backend", Glib::RefPtr)
_WRAP_PROPERTY("delay-apply", bool)
_WRAP_PROPERTY("has-unapplied", bool)
_WRAP_PROPERTY("path", std::string)
_IGNORE_PROPERTY("schema")
_WRAP_PROPERTY("schema-id", Glib::ustring)
_WRAP_PROPERTY("settings-schema", Glib::RefPtr, newin "2,58")
//TODO?: _WRAP_SIGNAL(bool change_event(const std::vector& keys, int n_keys), "change-event")
#m4 _CONVERSION(`const char*',`const Glib::ustring&',__GCHARP_TO_USTRING)
_WRAP_SIGNAL(void changed(const Glib::ustring& key), "changed", detail_name key)
_WRAP_SIGNAL(bool writable_change_event(GQuark key), "writable-change-event")
_WRAP_SIGNAL(void writable_changed(const Glib::ustring& key), writable_changed, detail_name key)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// SlotGetMapping and SlotSetMapping must be public. They are used in
// the anonymous namespace in settings.ccg.
/* A slot to be called to map values in a binding created by bind_value().
*
* For instance:
* @code
* bool map_from_setting_to_property(GValue* to_value, GVariant* from_variant);
* @endcode
*
* @return true if the mapping was successful, and false otherwise.
*/
using SlotGetMapping = sigc::slot;
/* A slot to be called to map values in a binding created by bind_value().
*
* For instance:
* @code
* GVariant* map_from_property_to_setting(
* const GValue* from_value, const GVariantType* expected_type);
* @endcode
*
* @return A new GVariant if the mapping was successful,
* and nullptr otherwise.
*/
using SlotSetMapping = sigc::slot;
#endif // DOXYGEN_SHOULD_SKIP_THIS
private:
void bind_value(const Glib::ustring& key,
Glib::ObjectBase* object, const Glib::ustring& property, BindFlags flags,
const SlotGetMapping& get_mapping, const SlotSetMapping& set_mapping);
// The functor GetMappingProp can be implicitly converted to a SlotGetMapping
// and used in a call to bind_value().
template
class GetMappingProp
{
public:
explicit GetMappingProp(const SlotTypedMapping& slot) : typed_mapping(slot) {}
bool operator()(GValue* to_value, GVariant* from_variant)
{
Glib::Variant from_glib_variant(from_variant, true);
const auto to = typed_mapping(from_glib_variant.get());
if (!to.has_value())
return false;
Glib::Value to_glib_value;
to_glib_value.init(to_value);
to_glib_value.set(*to);
g_value_copy(to_glib_value.gobj(), to_value);
return true;
}
private:
SlotTypedMapping typed_mapping;
}; // Settings::GetMappingProp
// The functor SetMappingProp can be implicitly converted to a SlotGetMapping
// and used in a call to bind_value().
template
class SetMappingProp
{
public:
explicit SetMappingProp(const SlotTypedMapping& slot) : typed_mapping(slot) {}
GVariant* operator()(const GValue* from_value, const GVariantType* /* expected_type */)
{
Glib::Value from_glib_value;
from_glib_value.init(from_value);
const auto to = typed_mapping(from_glib_value.get());
if (!to.has_value())
return nullptr;
auto to_glib_variant = Glib::Variant::create(*to);
return to_glib_variant.gobj_copy();
}
private:
SlotTypedMapping typed_mapping;
}; // Settings::SetMappingProp
}; // Settings
} // namespace Gio