Attribute Macro gsettings_macro::gen_settings
source · #[gen_settings]
Expand description
Macro for typesafe gio::Settings
key access.
The macro’s main purpose is to reduce the risk of mistyping a key,
using the wrong method to access values, inputting incorrect values,
and to reduce boilerplate. Additionally, the summary, description,
and default value are included in the documentation of each generated
method. This would be beneficial if you use tools like
rust-analyzer
.
⚠️ IMPORTANT ⚠️
Both gio
and glib
need to be in scope, so unless they are direct crate
dependencies, you need to import them because gen_settings
is using
them internally. For example:
use gtk::{gio, glib};
§Example
use gsettings_macro::gen_settings;
#[gen_settings(file = "./tests/io.github.seadve.test.gschema.xml")]
pub struct ApplicationSettings;
let settings = ApplicationSettings::new("io.github.seadve.test");
// `i` D-Bus type
settings.set_window_width(100);
assert_eq!(settings.window_width(), 100);
// enums
settings.set_alert_sound(AlertSound::Glass);
assert_eq!(settings.alert_sound(), AlertSound::Glass);
// bitflags
settings.set_space_style(SpaceStyle::BEFORE_COLON | SpaceStyle::BEFORE_COMMA);
assert_eq!(
settings.space_style(),
SpaceStyle::BEFORE_COLON | SpaceStyle::BEFORE_COMMA
);
Note: The file path is relative to the project root or where the
Cargo.toml
file is located.
§Generated methods
The procedural macro generates the following gio::Settings
methods
for each key in the schema:
set
->set_${key}
, which panics when writing in a readonly key, andtry_set_${key}
, which behaves the same as the original method.get
->${key}
connect_changed
->connect_${key}_changed
bind
->bind_${key}
create_action
->create_${key}_action
default_value
->${key}_default_value
reset
->reset_${key}
§Known D-Bus type signatures
The setter and getter methods has the following parameter and return type, depending on the key’s type signature.
Type Signature | Parameter Type | Return Type |
---|---|---|
b | bool | bool |
i | i32 | i32 |
u | u32 | u32 |
x | i64 | i64 |
t | u64 | u64 |
d | f64 | f64 |
(ii) | (i32, i32 ) | (i32, i32 ) |
as | &[&str] | Vec<String> |
s * | &str | String |
* If the key of type signature s
has no choice
attribute
specified in the GSchema, the parameter and return types stated
in the table would be applied. Otherwise, it will generate an
enum, like described in the next section, and use it as the parameter
and return types, instead of &str
and String
respectively.
It will not compile if the type signature is not defined above.
However, it is possible to explicitly skip generating methods
for a specific key or type signature using the attribute
#[gen_settings_skip]
, or define a custom parameter and return
types using #[gen_settings_define]
attribute. The usage of
the latter will be further explained in the following sections.
§Enums and Flags
The macro will also automatically generate enums or flags. If it is
an enum, it would generated a normal Rust enum with each nick
specified in the GSchema converted to pascal case as an enum variant.
The enum would implement both ToVariant
and FromVariant
, Clone
,
Hash
, PartialEq
, Eq
, PartialOrd
, and Ord
. On
the other hand, if it is a flag, it would generate bitflags
same as the bitflags generated by the bitflags
macro with each
nick specified in the GSchema converted to screaming snake case as
a const flag.
The generated types, enum or bitflags, would have the same visibility and scope with the generated struct.
§Skipping methods generation
This would be helpful if you want to have full control with the key without the macro intervening. For example:
use gsettings_macro::gen_settings;
#[gen_settings(
file = "./tests/io.github.seadve.test.gschema.xml",
id = "io.github.seadve.test"
)]
// Skip generating methods for keys with type signature `(ss)`
#[gen_settings_skip(signature = "(ss)")]
// Skip generating methods for the key of name `some-key-name`
#[gen_settings_skip(key_name = "some-key-name")]
pub struct Settings;
impl Settings {
pub fn set_some_key_name(value: &std::path::Path) {
...
}
}
§Defining custom types
use gsettings_macro::gen_settings;
use std::path::{Path, PathBuf};
#[gen_settings(file = "./tests/io.github.seadve.test.gschema.xml")]
// Define custom parameter and return types for keys with type `(ss)`
#[gen_settings_define(
signature = "(ss)",
arg_type = "(&str, &str)",
ret_type = "(String, String)"
)]
// Define custom parameter and return types for key with name `cache-dir`
#[gen_settings_define(key_name = "cache-dir", arg_type = "&Path", ret_type = "PathBuf")]
pub struct SomeAppSettings;
let settings = SomeAppSettings::new("io.github.seadve.test");
settings.set_cache_dir(Path::new("/some_dir"));
assert_eq!(settings.cache_dir(), PathBuf::from("/some_dir"));
settings.set_string_tuple(("hi", "hi2"));
assert_eq!(settings.string_tuple(), ("hi".into(), "hi2".into()));
The type specified in arg_type
and ret_type
has to be on scope or
you can specify the full path.
If you somehow do not want an enum parameter and return types for s
type signature with choices. You can also use this to override that behavior.
Note: The type has to implement both ToVariant
and FromVariant
or it
would fail to compile.
§Default trait
The schema id can be specified as an attribute, making it implement
Default
and create a new
constructor without parameters.
Otherwise, it will not implement Default
and would require the
schema id as an parameter in the the constructor or the new
method.
The following is an example of defining the id
attribute in the macro:
use gsettings_macro::gen_settings;
#[gen_settings(
file = "./tests/io.github.seadve.test.gschema.xml",
id = "io.github.seadve.test"
)]
pub struct ApplicationSettings;
// The id is specified above so it is not needed
// to specify it in the constructor.
let settings = ApplicationSettings::new();
let another_instance = ApplicationSettings::default();