[glib] Allow property actions to invert booleans



commit 1102e6f9ca89b54e4e1139cca80f97c7bfb72dc3
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Mar 29 14:00:36 2015 -0400

    Allow property actions to invert booleans
    
    This can be handy when you want to change the sense of a toggle
    in the UI without rewriting the underlying logic. Currently, this
    is just exposed as a construct-only property. We may add a
    convenience wrapper or a special !property syntax for this later.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=728489

 gio/gpropertyaction.c |   45 ++++++++++++++++++++++++++++++++++++++++++++-
 gio/tests/actions.c   |   31 +++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 1 deletions(-)
---
diff --git a/gio/gpropertyaction.c b/gio/gpropertyaction.c
index 8c4a495..52cee4b 100644
--- a/gio/gpropertyaction.c
+++ b/gio/gpropertyaction.c
@@ -93,6 +93,7 @@ struct _GPropertyAction
   gpointer            object;
   GParamSpec         *pspec;
   const GVariantType *state_type;
+  gboolean            invert_boolean;
 };
 
 /**
@@ -118,9 +119,18 @@ enum
   PROP_STATE_TYPE,
   PROP_STATE,
   PROP_OBJECT,
-  PROP_PROPERTY_NAME
+  PROP_PROPERTY_NAME,
+  PROP_INVERT_BOOLEAN
 };
 
+static gboolean
+g_property_action_get_invert_boolean (GAction *action)
+{
+  GPropertyAction *paction = G_PROPERTY_ACTION (action);
+
+  return paction->invert_boolean;
+}
+
 static const gchar *
 g_property_action_get_name (GAction *action)
 {
@@ -165,6 +175,10 @@ g_property_action_set_state (GPropertyAction *paction,
 
   g_value_init (&value, paction->pspec->value_type);
   g_settings_get_mapping (&value, variant, NULL);
+
+  if (paction->pspec->value_type == G_TYPE_BOOLEAN && paction->invert_boolean)
+    g_value_set_boolean (&value, !g_value_get_boolean (&value));
+
   g_object_set_property (paction->object, paction->pspec->name, &value);
   g_value_unset (&value);
 }
@@ -189,6 +203,10 @@ g_property_action_get_state (GAction *action)
 
   g_value_init (&value, paction->pspec->value_type);
   g_object_get_property (paction->object, paction->pspec->name, &value);
+
+  if (paction->pspec->value_type == G_TYPE_BOOLEAN && paction->invert_boolean)
+    g_value_set_boolean (&value, !g_value_get_boolean (&value));
+
   result = g_settings_set_mapping (&value, paction->state_type, NULL);
   g_value_unset (&value);
 
@@ -316,6 +334,10 @@ g_property_action_set_property (GObject      *object,
       g_property_action_set_property_name (paction, g_value_get_string (value));
       break;
 
+    case PROP_INVERT_BOOLEAN:
+      paction->invert_boolean = g_value_get_boolean (value);
+      break;
+
     default:
       g_assert_not_reached ();
     }
@@ -351,6 +373,10 @@ g_property_action_get_property (GObject    *object,
       g_value_take_variant (value, g_property_action_get_state (action));
       break;
 
+    case PROP_INVERT_BOOLEAN:
+      g_value_set_boolean (value, g_property_action_get_invert_boolean (action));
+      break;
+
     default:
       g_assert_not_reached ();
     }
@@ -515,6 +541,23 @@ g_property_action_class_init (GPropertyActionClass *class)
                                                         G_PARAM_WRITABLE |
                                                         G_PARAM_CONSTRUCT_ONLY |
                                                         G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GPropertyAction:invert-boolean:
+   *
+   * If %TRUE, the state of the action will be the negation of the
+   * property value, provided the property is boolean.
+   *
+   * Since: 2.46
+   */
+  g_object_class_install_property (object_class, PROP_INVERT_BOOLEAN,
+                                   g_param_spec_boolean ("invert-boolean",
+                                                         P_("Invert boolean"),
+                                                         P_("Whether to invert the value of a boolean 
property"),
+                                                         FALSE,
+                                                         G_PARAM_READWRITE |
+                                                         G_PARAM_CONSTRUCT_ONLY |
+                                                         G_PARAM_STATIC_STRINGS));
 }
 
 /**
diff --git a/gio/tests/actions.c b/gio/tests/actions.c
index 35de47f..8b5339e 100644
--- a/gio/tests/actions.c
+++ b/gio/tests/actions.c
@@ -1050,6 +1050,16 @@ test_property_actions (void)
   g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
   g_object_unref (action);
 
+  /* inverted */
+  action = g_object_new (G_TYPE_PROPERTY_ACTION,
+                         "name", "disable-proxy",
+                         "object", client,
+                         "property-name", "enable-proxy",
+                         "invert-boolean", TRUE,
+                         NULL);
+  g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
+  g_object_unref (action);
+
   /* enum... */
   action = g_property_action_new ("type", client, "type");
   g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action));
@@ -1062,6 +1072,7 @@ test_property_actions (void)
   ensure_state (group, "app-id", "'org.gtk.test'");
   ensure_state (group, "keepalive", "uint32 0");
   ensure_state (group, "tls", "false");
+  ensure_state (group, "disable-proxy", "false");
   ensure_state (group, "type", "'stream'");
 
   verify_changed (NULL);
@@ -1102,6 +1113,11 @@ test_property_actions (void)
   g_assert (g_socket_client_get_tls (client));
   ensure_state (group, "tls", "true");
 
+  g_action_group_change_action_state (G_ACTION_GROUP (group), "disable-proxy", g_variant_new ("b", TRUE));
+  verify_changed ("disable-proxy:true");
+  ensure_state (group, "disable-proxy", "true");
+  g_assert (!g_socket_client_get_enable_proxy (client));
+
   /* test toggle true->false */
   g_action_group_activate_action (G_ACTION_GROUP (group), "tls", NULL);
   verify_changed ("tls:false");
@@ -1118,6 +1134,21 @@ test_property_actions (void)
   verify_changed ("tls:false");
   ensure_state (group, "tls", "false");
 
+  /* now do the same for the inverted action */
+  g_action_group_activate_action (G_ACTION_GROUP (group), "disable-proxy", NULL);
+  verify_changed ("disable-proxy:false");
+  g_assert (g_socket_client_get_enable_proxy (client));
+  ensure_state (group, "disable-proxy", "false");
+
+  g_action_group_activate_action (G_ACTION_GROUP (group), "disable-proxy", NULL);
+  verify_changed ("disable-proxy:true");
+  g_assert (!g_socket_client_get_enable_proxy (client));
+  ensure_state (group, "disable-proxy", "true");
+
+  g_socket_client_set_enable_proxy (client, TRUE);
+  verify_changed ("disable-proxy:false");
+  ensure_state (group, "disable-proxy", "false");
+
   /* enum tests */
   g_action_group_change_action_state (G_ACTION_GROUP (group), "type", g_variant_new ("s", "datagram"));
   verify_changed ("type:'datagram'");


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