summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2013-04-05 13:34:42 -0400
committerRyan Lortie <desrt@desrt.ca>2013-04-08 14:32:00 -0400
commitc3279dd6a4bc27b06c271e5d8e41a8fb8057c786 (patch)
tree59f18861fb5e7ef0356f58ae9ab420de0d21e17d
parent5154a152777f02d6e2d67ca4dd877a7cee1b2c04 (diff)
downloadglib-wip/gobjectnew.tar.gz
-rw-r--r--gobject/gparam.c92
-rw-r--r--gobject/gparam.h2
-rw-r--r--gobject/gparamspecs.c51
-rw-r--r--gobject/gparamspecs.h11
4 files changed, 138 insertions, 18 deletions
diff --git a/gobject/gparam.c b/gobject/gparam.c
index 08f694d2e..0ead45ff1 100644
--- a/gobject/gparam.c
+++ b/gobject/gparam.c
@@ -545,18 +545,44 @@ g_param_spec_steal_qdata (GParamSpec *pspec,
* g_param_spec_get_redirect_target:
* @pspec: a #GParamSpec
*
- * If the paramspec redirects operations to another paramspec,
- * returns that paramspec. Redirect is used typically for
- * providing a new implementation of a property in a derived
- * type while preserving all the properties from the parent
- * type. Redirection is established by creating a property
- * of type #GParamSpecOverride. See g_object_class_override_property()
- * for an example of the use of this capability.
+ * Finds a #GParamSpec that is somehow related to @pspec.
+ *
+ * This function is confusing and annoying and has many caveats. You
+ * should probably not use it. Just about the only thing that it is
+ * useful for is to ascertain the type of #GParamSpec that originally
+ * defined an interface and in that case what you probably really want
+ * to know anyway can be obtained with G_PARAM_SPEC_VALUE_TYPE().
+ *
+ * For most #GParamSpec types this function returns %NULL.
+ *
+ * For #GParamSpecOverride, this function returns the highest-level
+ * #GParamSpec from which the chain of overrides derives. This is not,
+ * however, the same as finding the #GParamSpec that originally defined
+ * the interface that @pspec is implementing because it's possible to
+ * directly create a new #GParamSpec and install it on an interface that
+ * already has the same type of parameter, without #GParamSpecOverride,
+ * in which case this function will return %NULL. There is no general
+ * mechanism for answering the question of "what class or interface is
+ * this property defined on?" and in some cases it's possible that a
+ * property is defined in multiple places. One example is two
+ * properties of the same name and compatible types defined on two
+ * separate interfaces, both of which are implemented by an object.
+ * Another example is a property defined as read-only by a parent class
+ * and then having writability added by a subclass, in which case the
+ * 'readable' and 'writable' parts of the property are split across two
+ * separate interfaces.
+ *
+ * For #GParamSpecDefault, this function returns the highest-level
+ * #GParamSpec from which the chain of overrides of its corresponding
+ * implementation #GParamSpec derives. For #GParamSpecDefault you are
+ * probably more interested in using g_param_spec_get_implementation(),
+ * which returns the @pspec defined by the class which is implementing
+ * the property (ie: the class that will receive the property get/set
+ * calls).
*
* Since: 2.4
*
- * Returns: (transfer none): paramspec to which requests on this
- * paramspec should be redirected, or %NULL if none.
+ * Returns: (transfer none): a #GParamSpec as above, or %NULL
*/
GParamSpec*
g_param_spec_get_redirect_target (GParamSpec *pspec)
@@ -567,13 +593,61 @@ g_param_spec_get_redirect_target (GParamSpec *pspec)
{
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
+ /* No need to recurse: overridden was already fully-dereferenced
+ * when the GParmaSpecOverride was created.
+ */
return ospec->overridden;
}
+ else if (G_IS_PARAM_SPEC_DEFAULT (pspec))
+ {
+ GParamSpecDefault *dspec = G_PARAM_SPEC_DEFAULT (pspec);
+ GParamSpec *override;
+
+ override = g_param_spec_get_redirect_target (dspec->implementation);
+
+ return override ? override : dspec->implementation;
+ }
else
return NULL;
}
/**
+ * g_param_spec_get_implementation:
+ * @pspec: a #GParamSpec
+ *
+ * Gets the #GParamSpec defined by the class which implements the
+ * property described by @pspec.
+ *
+ * This is the class that will receive the property get/set calls when
+ * the parameter is used.
+ *
+ * In most cases, this function will just return @pspec itself. The
+ * case where this is not true is if @pspec is a #GParamSpecDefault. In
+ * that case, @pspec was defined by a subclass of the class that
+ * actually implements the property in order to override its default
+ * value; the original @pspec defined by the implementing class will be
+ * returned.
+ *
+ * Returns: (transfer none): the implementation #GParamSpec
+ *
+ * Since: 2.38
+ */
+GParamSpec *
+g_param_spec_get_implementation (GParamSpec *pspec)
+{
+ g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
+
+ if (G_IS_PARAM_SPEC_DEFAULT (pspec))
+ {
+ GParamSpecDefault *dspec = G_PARAM_SPEC_DEFAULT (pspec);
+
+ pspec = dspec->implementation;
+ }
+
+ return pspec;
+}
+
+/**
* g_param_value_set_default:
* @pspec: a valid #GParamSpec
* @value: a #GValue of correct type for @pspec
diff --git a/gobject/gparam.h b/gobject/gparam.h
index 315c428e4..7e198fab6 100644
--- a/gobject/gparam.h
+++ b/gobject/gparam.h
@@ -298,6 +298,8 @@ gpointer g_param_spec_steal_qdata (GParamSpec *pspec,
GQuark quark);
GLIB_AVAILABLE_IN_ALL
GParamSpec* g_param_spec_get_redirect_target (GParamSpec *pspec);
+GLIB_AVAILABLE_IN_2_38
+GParamSpec* g_param_spec_get_implementation (GParamSpec *pspec);
GLIB_AVAILABLE_IN_ALL
void g_param_value_set_default (GParamSpec *pspec,
diff --git a/gobject/gparamspecs.c b/gobject/gparamspecs.c
index 148148628..57d993d42 100644
--- a/gobject/gparamspecs.c
+++ b/gobject/gparamspecs.c
@@ -1067,7 +1067,7 @@ param_default_init (GParamSpec *pspec)
static void
param_default_finalize (GParamSpec *pspec)
{
- GParamSpecDefault *dspec = G_PARAM_SPEC_OVERRIDE (pspec);
+ GParamSpecDefault *dspec = G_PARAM_SPEC_DEFAULT (pspec);
GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_OVERRIDE));
if (dspec->implementation)
@@ -1085,16 +1085,16 @@ static void
param_default_set_default (GParamSpec *pspec,
GValue *value)
{
- GParamSpecDefault *dspec = G_PARAM_SPEC_OVERRIDE (pspec);
+ GParamSpecDefault *dspec = G_PARAM_SPEC_DEFAULT (pspec);
- g_value_copy (&dpspec->default_value, value);
+ g_value_copy (&dspec->default_value, value);
}
static gboolean
param_default_validate (GParamSpec *pspec,
GValue *value)
{
- GParamSpecDefault *dspec = G_PARAM_SPEC_OVERRIDE (pspec);
+ GParamSpecDefault *dspec = G_PARAM_SPEC_DEFAULT (pspec);
return g_param_value_validate (dspec->implementation, value);
}
@@ -1104,7 +1104,7 @@ param_default_values_cmp (GParamSpec *pspec,
const GValue *value1,
const GValue *value2)
{
- GParamSpecDefault *dspec = G_PARAM_SPEC_OVERRIDE (pspec);
+ GParamSpecDefault *dspec = G_PARAM_SPEC_DEFAULT (pspec);
return g_param_values_cmp (dspec->implementation, value1, value2);
}
@@ -2589,3 +2589,44 @@ g_param_spec_variant (const gchar *name,
return G_PARAM_SPEC (vspec);
}
+
+GParamSpec *
+g_param_spec_default (GParamSpec *implementation,
+ const GValue *new_value)
+{
+ GParamSpecDefault *dspec;
+ GParamSpec *pspec;
+ GValue my_copy;
+
+ g_return_val_if_fail (G_IS_PARAM_SPEC (implementation), NULL);
+ g_return_val_if_fail (G_VALUE_HOLDS (new_value, G_PARAM_SPEC_VALUE_TYPE (implementation)), NULL);
+
+ while (TRUE)
+ {
+ GParamSpec *indirect = g_param_spec_get_implementation (implementation);
+ if (indirect)
+ implementation = indirect;
+ else
+ break;
+ }
+
+ g_value_copy (new_value, &my_copy);
+ if (g_param_value_validate (implementation, &my_copy))
+ {
+ gchar *new_str = g_strdup_value_contents (new_value);
+
+ g_critical ("%s: invalid new default value (%s) given for the override to property `%s' of type `%s'",
+ G_STRFUNC, new_str, implementation->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (implementation)));
+ g_value_unset (&my_copy);
+ g_free (new_str);
+ return NULL;
+ }
+
+ dspec = g_param_spec_internal (G_TYPE_PARAM_DEFAULT, implementation->name, NULL, NULL, implementation->flags);
+ pspec = G_PARAM_SPEC (dspec);
+ pspec->value_type = G_PARAM_SPEC_VALUE_TYPE (implementation);
+ dspec->implementation = g_param_spec_ref (implementation);
+ dspec->default_value = my_copy;
+
+ return pspec;
+}
diff --git a/gobject/gparamspecs.h b/gobject/gparamspecs.h
index a7fc97fb8..86a7f5e4c 100644
--- a/gobject/gparamspecs.h
+++ b/gobject/gparamspecs.h
@@ -1024,14 +1024,14 @@ struct _GParamSpecVariant
*
* Since: 2.38
*/
-struct _GParamSpecVariant
+struct _GParamSpecDefault
{
GParamSpec parent_instance;
- GVariantType *type;
- GVariant *default_value;
+ GParamSpec *implementation;
+ GValue default_value;
/*< private >*/
- gpointer padding[4];
+ gpointer padding[2];
};
/* --- GParamSpec prototypes --- */
@@ -1192,6 +1192,9 @@ GParamSpec* g_param_spec_variant (const gchar *name,
const GVariantType *type,
GVariant *default_value,
GParamFlags flags);
+GLIB_AVAILABLE_IN_2_38
+GParamSpec* g_param_spec_default (GParamSpec *implementation,
+ const GValue *new_value);
/* --- internal --- */
/* We prefix variable declarations so they can