[glib] add a way to create a GAction from GSettings



commit 1d98d18f64edddddea314630e9830a56082c2639
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Jan 19 09:40:24 2012 -0500

    add a way to create a GAction from GSettings
    
    g_settings_create_action() will create a GAction for the named key,
    allowing it to be added to the action group of the application (so that
    the setting can be directly manipulated from menus, for example).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=668279

 docs/reference/gio/gio-sections.txt |    3 +
 gio/gio.symbols                     |    1 +
 gio/gsettings.c                     |  262 +++++++++++++++++++++++++++++++++++
 gio/gsettings.h                     |    3 +
 4 files changed, 269 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 09b5404..9d135e6 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -2354,6 +2354,9 @@ g_settings_unbind
 GSettingsBindSetMapping
 GSettingsBindGetMapping
 
+<SUBSECTION>
+g_settings_create_action
+
 <SUBSECTION Standard>
 GSettingsClass
 G_IS_SETTINGS
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 34b6436..2b51d69 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1140,6 +1140,7 @@ g_settings_apply
 g_settings_bind
 g_settings_bind_writable
 g_settings_bind_with_mapping
+g_settings_create_action
 g_settings_delay
 g_settings_get
 g_settings_get_child
diff --git a/gio/gsettings.c b/gio/gsettings.c
index 5898fdd..95f0489 100644
--- a/gio/gsettings.c
+++ b/gio/gsettings.c
@@ -31,6 +31,7 @@
 #include "gsettingsbackendinternal.h"
 #include "gsettings-mapping.h"
 #include "gsettingsschema-internal.h"
+#include "gaction.h"
 
 #include "strinfo.c"
 
@@ -2841,6 +2842,267 @@ g_settings_unbind (gpointer     object,
   g_object_set_qdata (object, binding_quark, NULL);
 }
 
+/* GAction {{{1 */
+
+typedef struct
+{
+  GObject parent_instance;
+
+  GSettingsSchemaKey key;
+  GSettings *settings;
+} GSettingsAction;
+
+typedef GObjectClass GSettingsActionClass;
+
+static GType g_settings_action_get_type (void);
+static void g_settings_action_iface_init (GActionInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (GSettingsAction, g_settings_action, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, g_settings_action_iface_init))
+
+enum
+{
+  ACTION_PROP_0,
+  ACTION_PROP_NAME,
+  ACTION_PROP_PARAMETER_TYPE,
+  ACTION_PROP_ENABLED,
+  ACTION_PROP_STATE_TYPE,
+  ACTION_PROP_STATE
+};
+
+static const gchar *
+g_settings_action_get_name (GAction *action)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+
+  return gsa->key.name;
+}
+
+static const GVariantType *
+g_settings_action_get_parameter_type (GAction *action)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+  const GVariantType *type;
+
+  type = g_variant_get_type (gsa->key.default_value);
+  if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
+    type = NULL;
+
+  return type;
+}
+
+static gboolean
+g_settings_action_get_enabled (GAction *action)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+
+  return g_settings_is_writable (gsa->settings, gsa->key.name);
+}
+
+static const GVariantType *
+g_settings_action_get_state_type (GAction *action)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+
+  return g_variant_get_type (gsa->key.default_value);
+}
+
+static GVariant *
+g_settings_action_get_state (GAction *action)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+  GVariant *value;
+
+  value = g_settings_read_from_backend (gsa->settings, &gsa->key);
+
+  if (value == NULL)
+    value = g_settings_schema_key_get_translated_default (&gsa->key);
+
+  if (value == NULL)
+    value = g_variant_ref (gsa->key.default_value);
+
+  return value;
+}
+
+static GVariant *
+g_settings_action_get_state_hint (GAction *action)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+
+  /* no point in reimplementing this... */
+  return g_settings_get_range (gsa->settings, gsa->key.name);
+}
+
+static void
+g_settings_action_change_state (GAction  *action,
+                                GVariant *value)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+
+  if (g_settings_schema_key_type_check (&gsa->key, value) && g_settings_schema_key_range_check (&gsa->key, value))
+    g_settings_write_to_backend (gsa->settings, &gsa->key, value);
+}
+
+static void
+g_settings_action_activate (GAction  *action,
+                            GVariant *parameter)
+{
+  GSettingsAction *gsa = (GSettingsAction *) action;
+
+  if (g_variant_is_of_type (gsa->key.default_value, G_VARIANT_TYPE_BOOLEAN))
+    {
+      GVariant *old;
+
+      if (parameter != NULL)
+        return;
+
+      old = g_settings_action_get_state (action);
+      parameter = g_variant_new_boolean (!g_variant_get_boolean (old));
+      g_variant_unref (old);
+    }
+
+  g_action_change_state (action, parameter);
+}
+
+static void
+g_settings_action_get_property (GObject *object, guint prop_id,
+                                GValue *value, GParamSpec *pspec)
+{
+  GAction *action = G_ACTION (object);
+
+  switch (prop_id)
+    {
+    case ACTION_PROP_NAME:
+      g_value_set_string (value, g_settings_action_get_name (action));
+      break;
+
+    case ACTION_PROP_PARAMETER_TYPE:
+      g_value_set_boxed (value, g_settings_action_get_parameter_type (action));
+      break;
+
+    case ACTION_PROP_ENABLED:
+      g_value_set_boolean (value, g_settings_action_get_enabled (action));
+      break;
+
+    case ACTION_PROP_STATE_TYPE:
+      g_value_set_boxed (value, g_settings_action_get_state_type (action));
+      break;
+
+    case ACTION_PROP_STATE:
+      g_value_set_variant (value, g_settings_action_get_state (action));
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+g_settings_action_finalize (GObject *object)
+{
+  GSettingsAction *gsa = (GSettingsAction *) object;
+
+  g_signal_handlers_disconnect_by_data (gsa->settings, gsa);
+  g_object_unref (gsa->settings);
+
+  G_OBJECT_CLASS (g_settings_action_parent_class)
+    ->finalize (object);
+}
+
+static void
+g_settings_action_init (GSettingsAction *gsa)
+{
+}
+
+static void
+g_settings_action_iface_init (GActionInterface *iface)
+{
+  iface->get_name = g_settings_action_get_name;
+  iface->get_parameter_type = g_settings_action_get_parameter_type;
+  iface->get_enabled = g_settings_action_get_enabled;
+  iface->get_state_type = g_settings_action_get_state_type;
+  iface->get_state = g_settings_action_get_state;
+  iface->get_state_hint = g_settings_action_get_state_hint;
+  iface->change_state = g_settings_action_change_state;
+  iface->activate = g_settings_action_activate;
+}
+
+static void
+g_settings_action_class_init (GSettingsActionClass *class)
+{
+  class->get_property = g_settings_action_get_property;
+  class->finalize = g_settings_action_finalize;
+
+  g_object_class_override_property (class, ACTION_PROP_NAME, "name");
+  g_object_class_override_property (class, ACTION_PROP_PARAMETER_TYPE, "parameter-type");
+  g_object_class_override_property (class, ACTION_PROP_ENABLED, "enabled");
+  g_object_class_override_property (class, ACTION_PROP_STATE_TYPE, "state-type");
+  g_object_class_override_property (class, ACTION_PROP_STATE, "state");
+}
+
+static void
+g_settings_action_changed (GSettings   *settings,
+                           const gchar *key,
+                           gpointer     user_data)
+{
+  g_object_notify (user_data, "state");
+}
+
+static void
+g_settings_action_enabled_changed (GSettings   *settings,
+                                   const gchar *key,
+                                   gpointer     user_data)
+{
+  g_object_notify (user_data, "enabled");
+}
+
+/**
+ * g_settings_create_action:
+ * @settings: a #GSettings
+ * @key: the name of a key in @settings
+ *
+ * Creates a #GAction corresponding to a given #GSettings key.
+ *
+ * The action has the same name as the key.
+ *
+ * The value of the key becomes the state of the action and the action
+ * is enabled when the key is writable.  Changing the state of the
+ * action results in the key being written to.  Changes to the value or
+ * writability of the key cause appropriate change notifications to be
+ * emitted for the action.
+ *
+ * For boolean-valued keys, action activations take no parameter and
+ * result in the toggling of the value.  For all other types,
+ * activations take the new value for the key (which must have the
+ * correct type).
+ *
+ * Returns: (transfer full): a new #GAction
+ *
+ * Since: 2.32
+ **/
+GAction *
+g_settings_create_action (GSettings   *settings,
+                          const gchar *key)
+{
+  GSettingsAction *gsa;
+  gchar *detailed_signal;
+
+  g_return_val_if_fail (G_IS_SETTINGS (settings), NULL);
+  g_return_val_if_fail (key != NULL, NULL);
+
+  gsa = g_object_new (g_settings_action_get_type (), NULL);
+  gsa->settings = g_object_ref (settings);
+  g_settings_schema_key_init (&gsa->key, settings->priv->schema, key);
+
+  detailed_signal = g_strdup_printf ("changed::%s", key);
+  g_signal_connect (settings, detailed_signal, G_CALLBACK (g_settings_action_changed), gsa);
+  g_free (detailed_signal);
+  detailed_signal = g_strdup_printf ("writable-changed::%s", key);
+  g_signal_connect (settings, detailed_signal, G_CALLBACK (g_settings_action_enabled_changed), gsa);
+  g_free (detailed_signal);
+
+  return G_ACTION (gsa);
+}
+
 /* Epilogue {{{1 */
 
 /* vim:set foldmethod=marker: */
diff --git a/gio/gsettings.h b/gio/gsettings.h
index 80b9990..5c18842 100644
--- a/gio/gsettings.h
+++ b/gio/gsettings.h
@@ -267,6 +267,9 @@ void                    g_settings_bind_writable                        (GSettin
 void                    g_settings_unbind                               (gpointer                 object,
                                                                          const gchar             *property);
 
+GAction *               g_settings_create_action                        (GSettings               *settings,
+                                                                         const gchar             *key);
+
 gpointer                g_settings_get_mapped                           (GSettings               *settings,
                                                                          const gchar             *key,
                                                                          GSettingsGetMapping      mapping,



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