Endpoint to set arbitrary settings

This commit is contained in:
Kovid Goyal 2025-05-19 19:07:37 +05:30
parent d38d72bd5e
commit fcc77c264f
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
2 changed files with 79 additions and 1 deletions

View file

@ -71,6 +71,37 @@ func EntryPoint(root *cli.Command) {
return utils.IfElse(err == nil, 0, 1), err
},
})
st := parent.AddSubCommand(&cli.Command{
Name: "set-setting",
ShortDescription: "Change an arbitrary setting",
Usage: " key [value]",
HelpText: "Set an arbitrary setting. If you want to set the color-scheme use the dedicated command for it. Use this command with care as it does no validation for the type of value. The syntax for specifying values is described at: :link:`the glib docs <https://docs.gtk.org/glib/gvariant-text-format.html>`. Leaving out the value or specifying an empty value, will delete the setting.",
Run: func(cmd *cli.Command, args []string) (rc int, err error) {
val := ""
if len(args) < 1 {
cmd.ShowHelp()
return 1, fmt.Errorf("must specify the key")
}
if len(args) > 1 {
val = args[1]
}
opts := SetOptions{}
if err = cmd.GetOptionValues(&opts); err == nil {
err = set_setting(args[0], val, &opts)
}
return utils.IfElse(err == nil, 0, 1), err
},
})
st.Add(cli.OptionSpec{
Name: "--namespace -n",
Help: "The namespace in which to change the setting.",
Default: PORTAL_APPEARANCE_NAMESPACE,
})
st.Add(cli.OptionSpec{
Name: "--data-type",
Help: "The DBUS data type signature of the value. The default is to guess from the textual representation, see :link:`the glib docs <https://docs.gtk.org/glib/gvariant-text-format.html>` for details.",
})
ss := parent.AddSubCommand(&cli.Command{
Name: "show-settings",
ShortDescription: "Print the current values of the desktop settings",

View file

@ -171,6 +171,7 @@ func (self *Portal) Start() (err error) {
}
methods = MethodSpec{
"ChangeSetting": {{"namespace", "s", false}, {"key", "s", false}, {"value", "v", false}},
"RemoveSetting": {{"namespace", "s", false}, {"key", "s", false}},
}
props["version"].Value = uint32(1)
if err = ExportInterface(self.bus, self, CHANGE_SETTINGS_INTERFACE, CHANGE_SETTINGS_OBJECT_PATH, methods, props, nil); err != nil {
@ -189,7 +190,10 @@ func ParseValueWithSignature(value, value_type_signature string) (v dbus.Variant
}
v, err = dbus.ParseVariant(value, s)
if err != nil {
return dbus.Variant{}, fmt.Errorf("%s is not a valid value for signature: %s with error: %w", value, value_type_signature, err)
if value_type_signature == "" {
return dbus.Variant{}, fmt.Errorf("could not guess the data type of: %s with error: %w", value, err)
}
return dbus.Variant{}, fmt.Errorf("%s is not a valid value for signature: %#v with error: %w", value, value_type_signature, err)
}
return v, nil
}
@ -414,6 +418,35 @@ Exec=kitten run-server
// }}}
type SetOptions struct {
Namespace, DataType string
}
func set_setting(key, value string, opts *SetOptions) (err error) {
conn, err := dbus.SessionBus()
if err != nil {
return fmt.Errorf("failed to connect to system bus with error: %w", err)
}
defer conn.Close()
method := "ChangeSetting"
var vals = []any{opts.Namespace, key}
if value == "" {
method = "RemoveSetting"
} else {
v, err := ParseValueWithSignature(value, opts.DataType)
if err != nil {
return err
}
vals = append(vals, v)
}
obj := conn.Object(PORTAL_BUS_NAME, dbus.ObjectPath(CHANGE_SETTINGS_OBJECT_PATH))
call := obj.Call(CHANGE_SETTINGS_INTERFACE+"."+method, dbus.FlagNoAutoStart, vals...)
if err = call.Store(); err != nil {
return fmt.Errorf("failed to call %s with error: %w", method, err)
}
return
}
func set_color_scheme(which string) (err error) {
conn, err := dbus.SessionBus()
if err != nil {
@ -479,6 +512,20 @@ func (self *Portal) ChangeSetting(namespace, key string, value dbus.Variant) *db
return nil
}
func (self *Portal) RemoveSetting(namespace, key string) *dbus.Error {
self.lock.Lock()
defer self.lock.Unlock()
existed := false
if m := self.settings[namespace]; m != nil {
_, existed = m[key]
}
if !existed {
return nil
}
delete(self.settings[namespace], key)
return nil
}
func (self *Portal) Read(namespace, key string) (dbus.Variant, *dbus.Error) {
self.lock.Lock()
defer self.lock.Unlock()