[gnome-terminal] settings: Import some backend specific code from glib



commit 267e79ee128a956da7769882e5c7d29967cebac6
Author: Christian Persch <chpe src gnome org>
Date:   Fri Aug 26 22:10:31 2022 +0200

    settings: Import some backend specific code from glib

 src/meson.build                      |   9 +-
 src/terminal-settings-bridge-impl.cc |  60 +++---
 src/terminal-settings-utils.cc       | 356 +++++++++++++++++++++++++++++++++++
 src/terminal-settings-utils.hh       |  62 ++++++
 4 files changed, 446 insertions(+), 41 deletions(-)
---
diff --git a/src/meson.build b/src/meson.build
index 456ba6b2..72ead5ab 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -123,6 +123,11 @@ settings_dbus_sources = gnome.gdbus_codegen(
   object_manager: false,
 )
 
+settings_utils_sources = files(
+  'terminal-settings-utils.cc',
+  'terminal-settings-utils.hh',
+)
+
 regex_sources = files(
   'terminal-regex.hh',
 )
@@ -183,7 +188,7 @@ server_resources_sources = gnome.compile_resources(
   export: false,
 )
 
-server_sources = app_sources + client_util_sources + debug_sources + dbus_sources + egg_sources + 
i18n_sources + marshal_sources + misc_sources + profiles_sources + regex_sources + server_resources_sources + 
settings_dbus_sources + types_sources + util_sources + version_sources + files(
+server_sources = app_sources + client_util_sources + debug_sources + dbus_sources + egg_sources + 
i18n_sources + marshal_sources + misc_sources + profiles_sources + regex_sources + server_resources_sources + 
settings_dbus_sources + settings_utils_sources + types_sources + util_sources + version_sources + files(
   'server.cc',
   'terminal-enums.hh',
   'terminal-gdbus.cc',
@@ -312,7 +317,7 @@ prefs_resources_sources = gnome.compile_resources(
   export: false,
 )
 
-prefs_main_sources = app_sources + client_util_sources + debug_sources + i18n_sources + marshal_sources + 
misc_sources + prefs_resources_sources + profiles_sources + settings_dbus_sources + types_sources + 
util_sources + version_sources + files(
+prefs_main_sources = app_sources + client_util_sources + debug_sources + i18n_sources + marshal_sources + 
misc_sources + prefs_resources_sources + profiles_sources + settings_dbus_sources + settings_utils_sources + 
types_sources + util_sources + version_sources + files(
   'prefs-main.cc',
   'profile-editor.cc',
   'profile-editor.hh',
diff --git a/src/terminal-settings-bridge-impl.cc b/src/terminal-settings-bridge-impl.cc
index 57ea4285..14ab3682 100644
--- a/src/terminal-settings-bridge-impl.cc
+++ b/src/terminal-settings-bridge-impl.cc
@@ -26,6 +26,7 @@
 #include "terminal-dconf.hh"
 #include "terminal-debug.hh"
 #include "terminal-libgsystem.hh"
+#include "terminal-settings-utils.hh"
 #include "terminal-settings-bridge-generated.h"
 
 #include <gio/gio.h>
@@ -39,7 +40,6 @@ struct _TerminalSettingsBridgeImpl {
   TerminalSettingsBridgeSkeleton parent_instance;
 
   GSettingsBackend* backend;
-  GSettingsBackendClass* backend_class;
   void* tag;
 };
 
@@ -60,21 +60,6 @@ IMPL(T* that) noexcept
   return reinterpret_cast<TerminalSettingsBridgeImpl*>(that);
 }
 
-static inline int
-compare_string(void const* a,
-               void const* b,
-               void* closure)
-{
-  return strcmp(reinterpret_cast<char const*>(a), reinterpret_cast<char const*>(b));
-}
-
-static void
-unref_variant0(void* data) noexcept
-{
-  if (data)
-    g_variant_unref(reinterpret_cast<GVariant*>(data));
-}
-
 static GVariantType*
 type_from_string(GDBusMethodInvocation* invocation,
                  char const* type) noexcept
@@ -216,7 +201,7 @@ terminal_settings_bridge_impl_get_writable(TerminalSettingsBridge* object,
                         key);
 
   auto const impl = IMPL(object);
-  auto const v = impl->backend_class->get_writable(impl->backend, key);
+  auto const v = terminal_g_settings_backend_get_writable(impl->backend, key);
   return success(invocation, v);
 }
 
@@ -236,10 +221,10 @@ terminal_settings_bridge_impl_read(TerminalSettingsBridge* object,
     return true;
 
   auto const impl = IMPL(object);
-  gs_unref_variant auto v = impl->backend_class->read(impl->backend, key, vtype, default_value);
-  if (v)
-    g_variant_take_ref(v);
-
+  gs_unref_variant auto v = terminal_g_settings_backend_read(impl->backend,
+                                                             key,
+                                                             vtype,
+                                                             default_value);
   g_variant_type_free(vtype);
   return wrap(invocation, v);
 }
@@ -259,10 +244,9 @@ terminal_settings_bridge_impl_read_user_value(TerminalSettingsBridge* object,
     return true;
 
   auto const impl = IMPL(object);
-  gs_unref_variant auto v = impl->backend_class->read_user_value(impl->backend, key, vtype);
-  if (v)
-    g_variant_take_ref(v);
-
+  gs_unref_variant auto v = terminal_g_settings_backend_read_user_value(impl->backend,
+                                                                        key,
+                                                                        vtype);
   g_variant_type_free(vtype);
   return wrap(invocation, v);
 }
@@ -277,7 +261,7 @@ terminal_settings_bridge_impl_reset(TerminalSettingsBridge* object,
                         key);
 
   auto const impl = IMPL(object);
-  impl->backend_class->reset(impl->backend, key, impl->tag);
+  terminal_g_settings_backend_reset(impl->backend, key, impl->tag);
   return nothing(invocation);
 }
 
@@ -291,7 +275,7 @@ terminal_settings_bridge_impl_subscribe(TerminalSettingsBridge* object,
                         name);
 
   auto const impl = IMPL(object);
-  impl->backend_class->subscribe(impl->backend, name);
+  terminal_g_settings_backend_subscribe(impl->backend, name);
   return nothing(invocation);
 }
 
@@ -303,7 +287,7 @@ terminal_settings_bridge_impl_sync(TerminalSettingsBridge* object,
                         "Bridge impl ::sync\n");
 
   auto const impl = IMPL(object);
-  impl->backend_class->sync(impl->backend);
+  terminal_g_settings_backend_sync(impl->backend);
   return nothing(invocation);
 }
 
@@ -317,7 +301,7 @@ terminal_settings_bridge_impl_unsubscribe(TerminalSettingsBridge* object,
                         name);
 
   auto const impl = IMPL(object);
-  impl->backend_class->subscribe(impl->backend, name);
+  terminal_g_settings_backend_unsubscribe(impl->backend, name);
   return nothing(invocation);
 }
 
@@ -334,8 +318,10 @@ terminal_settings_bridge_impl_write(TerminalSettingsBridge* object,
                         "Bridge impl ::write key %s value %s\n",
                         key, v ? g_variant_print(v, true): "(null)");
 
-  gs_unref_variant auto holder = g_variant_ref_sink(v);
-  auto const r = impl->backend_class->write(impl->backend, key, v, impl->tag);
+  auto const r = terminal_g_settings_backend_write(impl->backend,
+                                                   key,
+                                                   v,
+                                                   impl->tag);
   return success(invocation, r);
 }
 
@@ -349,10 +335,7 @@ terminal_settings_bridge_impl_write_tree(TerminalSettingsBridge* object,
                         "Bridge impl ::write_tree path-prefix %s\n",
                         path_prefix);
 
-  auto const tree = g_tree_new_full(compare_string,
-                                    nullptr,
-                                    g_free,
-                                    unref_variant0);
+  auto const tree = terminal_g_settings_backend_create_tree();
 
   auto iter = GVariantIter{};
   g_variant_iter_init(&iter, tree_value);
@@ -366,7 +349,9 @@ terminal_settings_bridge_impl_write_tree(TerminalSettingsBridge* object,
   }
 
   auto const impl = IMPL(object);
-  auto const v = impl->backend_class->write_tree(impl->backend, tree, impl->tag);
+  auto const v = terminal_g_settings_backend_write_tree(impl->backend,
+                                                        tree,
+                                                        impl->tag);
 
   g_tree_unref(tree);
   return success(invocation, v);
@@ -410,15 +395,12 @@ terminal_settings_bridge_impl_constructed(GObject* object) noexcept
 
   auto const impl = IMPL(object);
   assert(impl->backend);
-  impl->backend_class = G_SETTINGS_BACKEND_GET_CLASS(impl->backend);
-  assert(impl->backend_class);
 }
 
 static void
 terminal_settings_bridge_impl_finalize(GObject* object) noexcept
 {
   auto const impl = IMPL(object);
-  impl->backend_class = nullptr;
   g_clear_object(&impl->backend);
 
   G_OBJECT_CLASS(terminal_settings_bridge_impl_parent_class)->finalize(object);
diff --git a/src/terminal-settings-utils.cc b/src/terminal-settings-utils.cc
new file mode 100644
index 00000000..9110d4b5
--- /dev/null
+++ b/src/terminal-settings-utils.cc
@@ -0,0 +1,356 @@
+/*
+ *  Copyright © 2008, 2010, 2011, 2022 Christian Persch
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#define G_SETTINGS_ENABLE_BACKEND
+
+#include "terminal-settings-utils.hh"
+
+#include <gio/gio.h>
+
+// BEGIN copied from glib/gio/gsettingsbackend.c
+
+/*
+ * Copyright © 2009, 2010 Codethink Limited
+ * Copyright © 2010 Red Hat, Inc.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ *          Matthias Clasen <mclasen redhat com>
+ */
+
+static void
+variant_unref0(void* data)
+{
+  if (data)
+    g_variant_unref(reinterpret_cast<GVariant*>(data));
+}
+
+static int
+compare_string(void const* a,
+               void const* b,
+               void* closure)
+{
+  return strcmp(reinterpret_cast<char const*>(a),
+                reinterpret_cast<char const*>(b));
+}
+
+/*
+ * terminal_g_settings_backend_create_tree:
+ *
+ * This is a convenience function for creating a tree that is compatible
+ * with terminal_g_settings_backend_write().  It merely calls g_tree_new_full()
+ * with strcmp(), g_free() and g_variant_unref().
+ *
+ * Returns: (transfer full): a new #GTree
+ */
+GTree*
+terminal_g_settings_backend_create_tree(void)
+{
+  return g_tree_new_full(compare_string, nullptr,
+                         g_free,
+                         variant_unref0);
+}
+
+/*
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ *          Matthias Clasen <mclasen redhat com>
+ */
+
+/*
+ * g_settings_backend_read:
+ * @backend: a #GSettingsBackend implementation
+ * @key: the key to read
+ * @expected_type: a #GVariantType
+ * @default_value: if the default value should be returned
+ *
+ * Reads a key. This call will never block.
+ *
+ * If the key exists, the value associated with it will be returned.
+ * If the key does not exist, %nullptr will be returned.
+ *
+ * The returned value will be of the type given in @expected_type.  If
+ * the backend stored a value of a different type then %nullptr will be
+ * returned.
+ *
+ * If @default_value is %TRUE then this gets the default value from the
+ * backend (ie: the one that the backend would contain if
+ * g_settings_reset() were called).
+ *
+ * Returns: (nullable) (transfer full): the value that was read, or %nullptr
+ */
+GVariant*
+terminal_g_settings_backend_read(GSettingsBackend* backend,
+                                 char const* key,
+                                 GVariantType const* expected_type,
+                                 gboolean default_value)
+{
+  auto value = G_SETTINGS_BACKEND_GET_CLASS(backend)->read (backend,
+                                                            key,
+                                                            expected_type,
+                                                            default_value);
+
+  if (value)
+    value = g_variant_take_ref(value);
+
+  if (value && !g_variant_is_of_type(value, expected_type)) [[unlikely]] {
+    g_clear_pointer(&value, g_variant_unref);
+  }
+
+  return value;
+}
+
+/*
+ * terminal_g_settings_backend_read_user_value:
+ * @backend: a #GSettingsBackend implementation
+ * @key: the key to read
+ * @expected_type: a #GVariantType
+ *
+ * Reads the 'user value' of a key.
+ *
+ * This is the value of the key that the user has control over and has
+ * set for themselves.  Put another way: if the user did not set the
+ * value for themselves, then this will return %nullptr(even if the
+ * sysadmin has provided a default value).
+ *
+ * Returns:(nullable)(transfer full): the value that was read, or %nullptr
+ */
+GVariant*
+terminal_g_settings_backend_read_user_value(GSettingsBackend* backend,
+                                            char const*key,
+                                            GVariantType const* expected_type)
+{
+  auto value = G_SETTINGS_BACKEND_GET_CLASS(backend)->read_user_value(backend,
+                                                                      key,
+                                                                      expected_type);
+
+  if (value)
+    value = g_variant_take_ref(value);
+
+  if (value && !g_variant_is_of_type(value, expected_type)) [[unlikely]] {
+    g_clear_pointer(&value, g_variant_unref);
+  }
+
+  return value;
+}
+
+/*
+ * terminal_g_settings_backend_write:
+ * @backend: a #GSettingsBackend implementation
+ * @key: the name of the key
+ * @value: a #GVariant value to write to this key
+ * @origin_tag: the origin tag
+ *
+ * Writes exactly one key.
+ *
+ * This call does not fail.  During this call a
+ * #GSettingsBackend::changed signal will be emitted if the value of the
+ * key has changed.  The updated key value will be visible to any signal
+ * callbacks.
+ *
+ * One possible method that an implementation might deal with failures is
+ * to emit a second "changed" signal(either during this call, or later)
+ * to indicate that the affected keys have suddenly "changed back" to their
+ * old values.
+ *
+ * If @value has a floating reference, it will be sunk.
+ *
+ * Returns: %TRUE if the write succeeded, %FALSE if the key was not writable
+ */
+gboolean
+terminal_g_settings_backend_write(GSettingsBackend* backend,
+                                  char const* key,
+                                  GVariant* value,
+                                  void* origin_tag)
+{
+  g_variant_ref_sink(value);
+  auto const success = G_SETTINGS_BACKEND_GET_CLASS(backend)->write(backend,
+                                                                    key,
+                                                                    value,
+                                                                    origin_tag);
+  g_variant_unref(value);
+
+  return success;
+}
+
+/*
+ * terminal_g_settings_backend_write_tree:
+ * @backend: a #GSettingsBackend implementation
+ * @tree: a #GTree containing key-value pairs to write
+ * @origin_tag: the origin tag
+ *
+ * Writes one or more keys.  This call will never block.
+ *
+ * The key of each item in the tree is the key name to write to and the
+ * value is a #GVariant to write.  The proper type of #GTree for this
+ * call can be created with terminal_g_settings_backend_create_tree().  This call
+ * might take a reference to the tree; you must not modified the #GTree
+ * after passing it to this call.
+ *
+ * This call does not fail.  During this call a #GSettingsBackend::changed
+ * signal will be emitted if any keys have been changed.  The new values of
+ * all updated keys will be visible to any signal callbacks.
+ *
+ * One possible method that an implementation might deal with failures is
+ * to emit a second "changed" signal(either during this call, or later)
+ * to indicate that the affected keys have suddenly "changed back" to their
+ * old values.
+ */
+gboolean
+terminal_g_settings_backend_write_tree(GSettingsBackend* backend,
+                                       GTree* tree,
+                                       void* origin_tag)
+{
+  return G_SETTINGS_BACKEND_GET_CLASS(backend)->write_tree(backend,
+                                                           tree,
+                                                           origin_tag);
+}
+
+/*
+ * terminal_g_settings_backend_reset:
+ * @backend: a #GSettingsBackend implementation
+ * @key: the name of a key
+ * @origin_tag: the origin tag
+ *
+ * "Resets" the named key to its "default" value(ie: after system-wide
+ * defaults, mandatory keys, etc. have been taken into account) or possibly
+ * unsets it.
+ */
+void
+terminal_g_settings_backend_reset(GSettingsBackend*backend,
+                                  char const* key,
+                                  void* origin_tag)
+{
+  G_SETTINGS_BACKEND_GET_CLASS(backend)->reset(backend, key, origin_tag);
+}
+
+/*
+ * terminal_g_settings_backend_get_writable:
+ * @backend: a #GSettingsBackend implementation
+ * @key: the name of a key
+ *
+ * Finds out if a key is available for writing to.  This is the
+ * interface through which 'lockdown' is implemented.  Locked down
+ * keys will have %FALSE returned by this call.
+ *
+ * You should not write to locked-down keys, but if you do, the
+ * implementation will deal with it.
+ *
+ * Returns: %TRUE if the key is writable
+ */
+gboolean
+terminal_g_settings_backend_get_writable(GSettingsBackend* backend,
+                                         char const* key)
+{
+  return G_SETTINGS_BACKEND_GET_CLASS(backend)->get_writable(backend, key);
+}
+
+/*
+ * terminal_g_settings_backend_unsubscribe:
+ * @backend: a #GSettingsBackend
+ * @name: a key or path to subscribe to
+ *
+ * Reverses the effect of a previous call to
+ * terminal_g_settings_backend_subscribe().
+ */
+void
+terminal_g_settings_backend_unsubscribe(GSettingsBackend* backend,
+                                        const char* name)
+{
+  G_SETTINGS_BACKEND_GET_CLASS(backend)->unsubscribe(backend, name);
+}
+
+/*
+ * terminal_g_settings_backend_subscribe:
+ * @backend: a #GSettingsBackend
+ * @name: a key or path to subscribe to
+ *
+ * Requests that change signals be emitted for events on @name.
+ */
+void
+terminal_g_settings_backend_subscribe(GSettingsBackend* backend,
+                                      char const* name)
+{
+  G_SETTINGS_BACKEND_GET_CLASS(backend)->subscribe(backend, name);
+}
+
+/*
+ * terminal_g_settings_backend_get_permission:
+ * @backend: a #GSettingsBackend
+ * @path: a path
+ *
+ * Gets the permission object associated with writing to keys below
+ * @path on @backend.
+ *
+ * If this is not implemented in the backend, then a %TRUE
+ * #GSimplePermission is returned.
+ *
+ * Returns:(not nullable)(transfer full): a non-%nullptr #GPermission.
+ *     Free with g_object_unref()
+ */
+GPermission*
+terminal_g_settings_backend_get_permission(GSettingsBackend* backend,
+                                           char const* path)
+{
+  auto const klass = G_SETTINGS_BACKEND_GET_CLASS(backend);
+  if (klass->get_permission)
+    return klass->get_permission(backend, path);
+
+  return g_simple_permission_new(TRUE);
+}
+
+/*
+ * terminal_g_settings_backend_sync_default:
+ *
+ * Syncs.
+ */
+void
+terminal_g_settings_backend_sync(GSettingsBackend* backend)
+{
+  auto const klass = G_SETTINGS_BACKEND_GET_CLASS(backend);
+  if (klass->sync)
+    klass->sync(backend);
+}
+
+// END copied from glib
diff --git a/src/terminal-settings-utils.hh b/src/terminal-settings-utils.hh
new file mode 100644
index 00000000..a64712b9
--- /dev/null
+++ b/src/terminal-settings-utils.hh
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2009, 2010 Codethink Limited
+ * Copyright © 2010 Red Hat, Inc.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ *          Matthias Clasen <mclasen redhat com>
+ */
+
+#pragma once
+
+#include <gio/gsettingsbackend.h>
+
+GTree* terminal_g_settings_backend_create_tree(void);
+
+GPermission* terminal_g_settings_backend_get_permission(GSettingsBackend* backend,
+                                                        char const*path);
+
+gboolean terminal_g_settings_backend_get_writable(GSettingsBackend* backend,
+                                                  const char* key);
+
+GVariant* terminal_g_settings_backend_read(GSettingsBackend* backend,
+                                           char const* key,
+                                           GVariantType const* expected_type,
+                                           gboolean default_value);
+
+GVariant* terminal_g_settings_backend_read_user_value(GSettingsBackend* backend,
+                                                      char const* key,
+                                                      GVariantType const* expected_type);
+
+void terminal_g_settings_backend_reset(GSettingsBackend* backend,
+                                       char const* key,
+                                       void* origin_tag);
+
+void terminal_g_settings_backend_subscribe(GSettingsBackend* backend,
+                                           const char* name);
+
+void terminal_g_settings_backend_sync(GSettingsBackend* backend);
+
+void terminal_g_settings_backend_unsubscribe(GSettingsBackend* backend,
+                                             const char* name);
+
+gboolean terminal_g_settings_backend_write(GSettingsBackend* backend,
+                                           char const* key,
+                                           GVariant* value,
+                                           void* origin_tag);
+
+gboolean terminal_g_settings_backend_write_tree(GSettingsBackend* backend,
+                                                      GTree*tree,
+                                                      void* origin_tag);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]