[gtk/ebassi/settings-builder: 1/3] Support binding properties to GSettings keys in GtkBuilder




commit 181fce834207df4ba845078fa61bf7246418e204
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Sep 9 19:12:40 2021 +0100

    Support binding properties to GSettings keys in GtkBuilder
    
    We already support binding properties; by adding new attributes to the
    `property` element we can automatically call g_settings_bind() on the
    object ourselves.

 gtk/gtkbuilder.c        | 16 +++++++++++
 gtk/gtkbuilderparser.c  | 76 ++++++++++++++++++++++++++++++++++++++++++-------
 gtk/gtkbuilderprivate.h | 14 +++++++++
 3 files changed, 96 insertions(+), 10 deletions(-)
---
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index 9d85e6f2ed..5139b36df1 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -719,6 +719,11 @@ gtk_builder_take_bindings (GtkBuilder *builder,
           BindingExpressionInfo *info = l->data;
           info->target = target;
         }
+      else if (common_info->tag_type == TAG_BINDING_SETTING)
+        {
+          BindingSettingsInfo *info = l->data;
+          info->target = target;
+        }
       else
         {
           g_assert_not_reached ();
@@ -1146,6 +1151,17 @@ gtk_builder_create_bindings (GtkBuilder  *builder,
 
           free_binding_expression_info (info);
         }
+      else if (common_info->tag_type == TAG_BINDING_SETTING)
+        {
+          BindingSettingsInfo *info = l->data;
+          GSettings *settings;
+
+          settings = g_settings_new (info->schema);
+          g_settings_bind (settings, info->key, info->target, info->target_pspec->name, info->flags);
+          g_object_unref (settings);
+
+          free_binding_settings_info (info);
+        }
       else
         g_assert_not_reached ();
     }
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index b9efb13fae..8185b5e3df 100644
--- a/gtk/gtkbuilderparser.c
+++ b/gtk/gtkbuilderparser.c
@@ -874,7 +874,8 @@ parse_property (ParserData   *data,
   const char *bind_source = NULL;
   const char *bind_property = NULL;
   const char *bind_flags_str = NULL;
-  GBindingFlags bind_flags = G_BINDING_DEFAULT;
+  const char *bind_schema = NULL;
+  const char *bind_key = NULL;
   gboolean translatable = FALSE;
   ObjectInfo *object_info;
   GParamSpec *pspec = NULL;
@@ -897,6 +898,8 @@ parse_property (ParserData   *data,
                                     G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-source", 
&bind_source,
                                     G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-property", 
&bind_property,
                                     G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-flags", 
&bind_flags_str,
+                                    G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, 
"bind-settings-schema", &bind_schema,
+                                    G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "bind-settings-key", 
&bind_key,
                                     G_MARKUP_COLLECT_INVALID))
     {
       _gtk_builder_prefix_error (data->builder, &data->ctx, error);
@@ -916,21 +919,59 @@ parse_property (ParserData   *data,
       return;
     }
 
-  if (bind_flags_str)
+  gtk_buildable_parse_context_get_position (&data->ctx, &line, &col);
+
+  if (bind_schema != NULL)
     {
-      if (!_gtk_builder_flags_from_string (G_TYPE_BINDING_FLAGS, NULL, bind_flags_str, &bind_flags, error))
+      GSettingsBindFlags bind_flags = G_SETTINGS_BIND_DEFAULT;
+
+      if (bind_flags_str)
         {
-          _gtk_builder_prefix_error (data->builder, &data->ctx, error);
-          return;
+          if (!_gtk_builder_flags_from_string (G_TYPE_SETTINGS_BIND_FLAGS, NULL, bind_flags_str, 
&bind_flags, error))
+            {
+              _gtk_builder_prefix_error (data->builder, &data->ctx, error);
+              return;
+            }
         }
-    }
 
-  gtk_buildable_parse_context_get_position (&data->ctx, &line, &col);
+      if (bind_key != NULL)
+        {
+          BindingSettingsInfo *binfo;
+
+          binfo = g_slice_new0 (BindingSettingsInfo);
+          binfo->tag_type = TAG_BINDING_SETTING;
+          binfo->target = NULL;
+          binfo->target_pspec = pspec;
+          binfo->schema = g_strdup (bind_schema);
+          binfo->key = g_strdup (bind_key);
+          binfo->flags = bind_flags;
+          binfo->line = line;
+          binfo->col = col;
 
-  if (bind_source)
+          object_info->bindings = g_slist_prepend (object_info->bindings, binfo);
+        }
+      else
+        {
+          error_missing_attribute (data, element_name,
+                                   "bind-settings-key",
+                                   error);
+          return;
+        }
+    }
+  else if (bind_source != NULL)
     {
+      GBindingFlags bind_flags = G_BINDING_DEFAULT;
       BindingInfo *binfo;
 
+      if (bind_flags_str)
+        {
+          if (!_gtk_builder_flags_from_string (G_TYPE_BINDING_FLAGS, NULL, bind_flags_str, &bind_flags, 
error))
+            {
+              _gtk_builder_prefix_error (data->builder, &data->ctx, error);
+              return;
+            }
+        }
+
       binfo = g_slice_new0 (BindingInfo);
       binfo->tag_type = TAG_BINDING;
       binfo->target = NULL;
@@ -943,7 +984,14 @@ parse_property (ParserData   *data,
 
       object_info->bindings = g_slist_prepend (object_info->bindings, binfo);
     }
-  else if (bind_property)
+  else if (bind_key != NULL)
+    {
+      error_missing_attribute (data, element_name,
+                               "bind-settings-schema",
+                               error);
+      return;
+    }
+  else if (bind_property != NULL)
     {
       error_missing_attribute (data, element_name,
                                "bind-source",
@@ -956,7 +1004,7 @@ parse_property (ParserData   *data,
   info->pspec = pspec;
   info->text = g_string_new ("");
   info->translatable = translatable;
-  info->bound = bind_source != NULL;
+  info->bound = bind_source != NULL || bind_schema != NULL;
   info->context = g_strdup (context);
   info->line = line;
   info->col = col;
@@ -1563,6 +1611,14 @@ free_binding_expression_info (BindingExpressionInfo *info)
   g_slice_free (BindingExpressionInfo, info);
 }
 
+void
+free_binding_settings_info (BindingSettingsInfo *info)
+{
+  g_free (info->schema);
+  g_free (info->key);
+  g_slice_free (BindingSettingsInfo, info);
+}
+
 static void
 free_requires_info (RequiresInfo *info,
                     gpointer      user_data)
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
index 34a48dd454..8dd2c7df52 100644
--- a/gtk/gtkbuilderprivate.h
+++ b/gtk/gtkbuilderprivate.h
@@ -27,6 +27,7 @@ enum {
   TAG_PROPERTY,
   TAG_BINDING,
   TAG_BINDING_EXPRESSION,
+  TAG_BINDING_SETTING,
   TAG_REQUIRES,
   TAG_OBJECT,
   TAG_CHILD,
@@ -141,6 +142,18 @@ typedef struct
   int col;
 } BindingExpressionInfo;
 
+typedef struct
+{
+  guint tag_type;
+  GObject *target;
+  GParamSpec *target_pspec;
+  char *schema;
+  char *key;
+  GSettingsBindFlags flags;
+  int line;
+  int col;
+} BindingSettingsInfo;
+
 typedef struct {
   guint    tag_type;
   char    *library;
@@ -228,6 +241,7 @@ void _free_signal_info (SignalInfo *info,
 void _free_binding_info (BindingInfo *info,
                          gpointer user_data);
 void free_binding_expression_info (BindingExpressionInfo *info);
+void free_binding_settings_info (BindingSettingsInfo *info);
 GtkExpression * expression_info_construct (GtkBuilder      *builder,
                                            ExpressionInfo  *info,
                                            GError         **error);


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