mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
If the user passes an explicit setter function when creating a GProperty, we assume that a notify signal will be emitted. For direct access to a structure field, we can emit an implicit notification ourselves, since we know that if the value has changed. This changes the signature of the explicit setter functions.
4965 lines
132 KiB
C
4965 lines
132 KiB
C
/* gproperty.c: Property definitions for GObject
|
|
*
|
|
* Copyright © 2013 Emmanuele Bassi <ebassi@gnome.org>
|
|
*
|
|
* 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 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, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/**
|
|
* SECTION:gproperty
|
|
* @Title: GProperty
|
|
* @Short_Desc: Property definitions for GObject
|
|
*
|
|
* #GProperty is a type of #GParamSpec for defining properties for #GObject.
|
|
*
|
|
* The main difference between #GProperty and #GParamSpec is that #GProperty
|
|
* enforces a specific set of best practices for accessing values exposed
|
|
* as #GObject properties.
|
|
*
|
|
* #GProperty uses direct access to the fields in the instance private data
|
|
* structure whenever possible, and allows specifying accessor functions in
|
|
* cases where it is necessary. For direct access, #GProperty assumes that
|
|
* the field is stored inside the per-instance private data structure.
|
|
*
|
|
* #GProperty is strongly typed, both at compilation time and at run time.
|
|
*
|
|
* Unlike #GParamSpec, there is a single public #GProperty class with various
|
|
* constructors; all public #GProperty methods operate depending on the type
|
|
* handled by the #GProperty.
|
|
*
|
|
* The #GParamSpec methods can be used with #GProperty transparently, to
|
|
* allow backward compatibility with existing code that introspects #GObject
|
|
* properties through the #GParamSpec API.
|
|
*
|
|
* <refsect2>
|
|
* <title>Using GProperty</title>
|
|
* <para>A typical example of #GProperty usage is:</para>
|
|
*
|
|
* |[
|
|
* /* the private data structure */
|
|
* struct _TestObjectPrivate
|
|
* {
|
|
* int x;
|
|
* int y;
|
|
* int width;
|
|
* int height;
|
|
* };
|
|
*
|
|
* static void
|
|
* test_object_class_init (TestObjectClass *klass)
|
|
* {
|
|
* G_DEFINE_PROPERTIES (TestObject, test_object, klass,
|
|
* G_DEFINE_PROPERTY (TestObject, int, x, G_PROPERTY_READWRITE)
|
|
* G_DEFINE_PROPERTY (TestObject, int, y, G_PROPERTY_READWRITE)
|
|
* G_DEFINE_PROPERTY (TestObject, int, width, G_PROPERTY_READWRITE)
|
|
* G_DEFINE_PROPERTY (TestObject, int, height, G_PROPERTY_READWRITE))
|
|
* }
|
|
* ]|
|
|
* <para>The main differences with the #GParamSpec creation and installation
|
|
* code are:</para>
|
|
*
|
|
* <itemizedlist>
|
|
* <listitem><para>the #GProperty constructors take the same number
|
|
* and types of parameters</para></listitem>
|
|
* <listitem><para>there are not #GObject set_property and get_property
|
|
* virtual function assignments</para></listitem>
|
|
* <listitem><para>all properties use direct access of the member in the
|
|
* instance private data structure</para></listitem>
|
|
* </itemizedlist>
|
|
*
|
|
* <refsect3>
|
|
* <title>Setting and getting values</title>
|
|
* <para>Writing generic accessors for properties defined using #GProperty
|
|
* is a simple case of calling g_property_set() or g_property_get(), for
|
|
* instance the code below is the simplest form of setter and getter
|
|
* pair for the "x" property as defined above:</para>
|
|
* |[
|
|
* void
|
|
* test_object_set_x (TestObject *self,
|
|
* int x)
|
|
* {
|
|
* g_return_if_fail (TEST_IS_OBJECT (self));
|
|
*
|
|
* g_property_set (G_PROPERTY (test_object_properties[PROP_X]), self, x);
|
|
* }
|
|
*
|
|
* int
|
|
* test_object_get_x (TestObject *self)
|
|
* {
|
|
* int retval;
|
|
*
|
|
* g_return_val_if_fail (TEST_IS_OBJECT (self), 0);
|
|
*
|
|
* g_property_get (G_PROPERTY (test_object_properties[PROP_X]),
|
|
* self,
|
|
* &retval);
|
|
*
|
|
* return retval;
|
|
* }
|
|
* ]|
|
|
* <para>Note that calling g_property_set() for a property holding a
|
|
* complex type (e.g. #GObject or #GBoxed) without a specific setter
|
|
* function will, by default, result in the pointer to the new value
|
|
* being copied in the private data structure's field; if you need to
|
|
* copy a boxed type, or take a reference on an object type, you will
|
|
* need to set the %G_PROPERTY_COPY_SET flag when creating the
|
|
* property.</para>
|
|
*
|
|
* <para>Calling g_property_get() will return a pointer to the private
|
|
* data structure's field, unless %G_PROPERTY_COPY_GET is set when
|
|
* creating the property, in which case the returned value will either
|
|
* be a copy of the private data structure field if it is a boxed type
|
|
* or the instance with its reference count increased if it is an object
|
|
* type.</para>
|
|
* </refsect3>
|
|
*
|
|
* <refsect3>
|
|
* <title>Ranges and validation</title>
|
|
* <para>For different property types it is possible to set a range of
|
|
* valid values; the setter function can then use g_property_validate()
|
|
* to check whether the new value is valid.</para>
|
|
*
|
|
* <para>The range is set using g_property_set_range():</para>
|
|
*
|
|
* |[
|
|
* G_DEFINE_PROPERTY_WITH_RANGE (TestObject, int, width,
|
|
* G_PROPERTY_READWRITE,
|
|
* 0, /* minimum value */
|
|
* G_MAXINT /* maximum value */)
|
|
* G_DEFINE_PROPERTY_WITH_RANGE (TestObject, int, height,
|
|
* G_PROPERTY_READWRITE,
|
|
* 0, /* minimum value */
|
|
* G_MAXINT /* maximum value */)
|
|
* ]|
|
|
*
|
|
* <para>The example above keeps the "width" and "height" properties as
|
|
* integers, but limits the range of valid values to [ 0, %G_MAXINT ].</para>
|
|
*
|
|
* <para>Validation is automatically performed when setting a property
|
|
* through g_property_set(); explicit setter methods can use g_property_validate()
|
|
* to perform the validation, e.g.:</para>
|
|
*
|
|
* |[
|
|
* void
|
|
* test_object_set_width (TestObject *self,
|
|
* int width)
|
|
* {
|
|
* GProperty *property;
|
|
*
|
|
* property = G_PROPERTY (test_object_properties[PROP_WIDTH]);
|
|
*
|
|
* g_return_if_fail (!g_property_validate (property, width));
|
|
*
|
|
* /* we deliberately do not use g_property_set() here because
|
|
* * g_property_set() will implicitly call g_property_validate()
|
|
* * prior to setting the property
|
|
* */
|
|
* if (self->priv->width == width)
|
|
* return;
|
|
*
|
|
* self->priv->width = width;
|
|
*
|
|
* g_object_notify_by_pspec (G_OBJECT (self), G_PARAM_SPEC (property));
|
|
*
|
|
* test_object_queue_foo (self);
|
|
* }
|
|
* ]|
|
|
* </refsect3>
|
|
*
|
|
* <refsect3>
|
|
* <title>Custom accessors</title>
|
|
* <para>For cases where the direct access to a structure field does not
|
|
* match the semantics of the property it is possible to pass a setter
|
|
* and a getter function when creating a #GProperty:</para>
|
|
*
|
|
* |[
|
|
* G_DEFINE_PROPERTY_EXTENDED (TestObject, object, complex,
|
|
* 0, /* no offset */
|
|
* test_object_set_complex_internal,
|
|
* test_object_get_complex_internal,
|
|
* G_PROPERTY_READWRITE,
|
|
* G_PROPERTY_PREREQUISITE (TEST_TYPE_COMPLEX))
|
|
* ]|
|
|
*
|
|
* <para>The accessors can be public or private functions. The implementation
|
|
* of the setter function should explicitly emit a notification when the
|
|
* property changes. An example of an explicit setter is:</para>
|
|
*
|
|
* |[
|
|
* static void
|
|
* test_object_set_complex_internal (gpointer self_,
|
|
* gpointer value_)
|
|
* {
|
|
* TestObject *self = self_;
|
|
* TestComplex *value = value_;
|
|
*
|
|
* /* no need to perform any work if the value is the same */
|
|
* if (self->priv->complex == value)
|
|
* return;
|
|
*
|
|
* if (self->priv->complex != NULL)
|
|
* {
|
|
* test_complex_set_back_pointer (self->priv->complex, NULL);
|
|
* g_object_unref (self->priv->complex);
|
|
* }
|
|
*
|
|
* self->priv->complex = value;
|
|
*
|
|
* if (self->priv->complex != NULL)
|
|
* {
|
|
* g_object_ref (self->priv->complex);
|
|
* test_complex_set_back_pointer (self->priv->complex, self);
|
|
* }
|
|
*
|
|
* test_object_queue_foo (self);
|
|
*
|
|
* g_object_notify (self, "complex");
|
|
* }
|
|
* ]|
|
|
*
|
|
* <para>It is also possible to still pass the offset of the structure
|
|
* field, and provide either the setter or the getter function:</para>
|
|
*
|
|
* |[
|
|
* G_DEFINE_PROPERTY_EXTENDED (TestObject, int, width,
|
|
* G_PRIVATE_OFFSET (TestObject, width),
|
|
* test_object_set_width_internal /* explicit */
|
|
* NULL, /* implicit */
|
|
* G_PROPERTY_READWRITE,
|
|
* G_PROPERTY_RANGE (0, G_MAXINT))
|
|
* ]|
|
|
*
|
|
* <para>Calling g_property_set() using the "width" property in the example
|
|
* above will result in calling test_object_set_width_internal(); calling,
|
|
* instead, g_property_get() using the "width" property will result in accessing
|
|
* the width structure member.</para>
|
|
*
|
|
* <warning><para>You must not call g_property_set() inside the implementation
|
|
* of test_object_set_width(), in order to avoid loops.</para></warning>
|
|
* </refsect3>
|
|
*
|
|
* <refsect3>
|
|
* <title>Special flags</title>
|
|
* <para>#GProperty has its own set of flags to be passed to its
|
|
* constructor functions. Alongside the usual %G_PROPERTY_READABLE
|
|
* and %G_PROPERTY_WRITABLE, which control the access policy for
|
|
* setter and getter functions, there are the following flags:</para>
|
|
*
|
|
* <itemizedlist>
|
|
* <listitem><para>%G_PROPERTY_DEPRECATED, a flag for marking
|
|
* deprecated properties. If the G_ENABLE_DIAGNOSTIC environment
|
|
* variable is set, calling g_property_set() and g_property_get()
|
|
* on the deprecated properties will result in a run time warning
|
|
* printed on the console.</para></listitem>
|
|
* <listitem><para>%G_PROPERTY_COPY_SET, a flag controlling the
|
|
* memory management semantics of the setter function. If this flag
|
|
* is set, the setter will make a copy (or take a reference) of
|
|
* the value passed to g_property_set().</para></listitem>
|
|
* <listitem><para>%G_PROPERTY_COPY_GET, a flag controlling the
|
|
* memory management semantics of the getter function. If this flag
|
|
* is set, the getter will make a copy (or take a reference) of
|
|
* the value return by g_property_get().</para></listitem>
|
|
* <listitem><para>%G_PROPERTY_CONSTRUCT_ONLY, a flag that
|
|
* establishes a property as being allowed to be set only during
|
|
* the instance construction.</para></listitem>
|
|
* </itemizedlist>
|
|
* </refsect3>
|
|
*
|
|
* <refsect3>
|
|
* <title>Property and accessor generation macros</title>
|
|
* <para>#GProperty provides a set of macros that allow to easily
|
|
* add properties to a #GObject type, as well as generating the
|
|
* public setter and getter pair of accessors to those
|
|
* properties.</para>
|
|
* <para>The G_DEFINE_PROPERTIES() and G_DEFINE_PROPERTY() macros
|
|
* abstract most of the boilerplate necessary to create properties
|
|
* and installing them on a #GObjectClass; the simplest form of
|
|
* the G_DEFINE_PROPERTY() macro assumes that the properties are
|
|
* going to be stored in the private data of an instance, and that
|
|
* the property's value is going to be directly accessed. It is
|
|
* also possible to use the variants of G_DEFINE_PROPERTY() to
|
|
* specify a range, or a default value for the property, or to
|
|
* execute custom code after the property has been created.</para>
|
|
* <para>The G_DEFINE_PROPERTY_EXTENDED(), on the other hand,
|
|
* allows specifying all the details of a property, including
|
|
* explicit setter and getter functions, or the offset of the
|
|
* property storage.</para>
|
|
* <para>The G_DEFINE_PROPERTY_SET() and G_DEFINE_PROPERTY_GET()
|
|
* macros define a public setter and getter functions, respectively,
|
|
* that will automatically and safely access the property.</para>
|
|
* <para>The G_DEFINE_PROPERTY_GET() macro generates code that
|
|
* will directly access the property storage, for performance
|
|
* purposes, whereas the G_DEFINE_PROPERTY_SET() macro will generate
|
|
* code that will call g_property_set(). If you need to access the
|
|
* property using g_property_get(), you can use the
|
|
* G_DEFINE_PROPERTY_INDIRECT_GET() macro, instead.</para>
|
|
* <para>Both macros have a WITH_CODE variant that allows injecting
|
|
* custom code inside the accessors.</para>
|
|
* <para>For convenience, there is also a G_DEFINE_PROPERTY_GET_SET()
|
|
* macro, which provides a short-hand for defining both getter and
|
|
* setter functions.</para>
|
|
* </refsect3>
|
|
*
|
|
* </refsect2>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "gproperty.h"
|
|
|
|
#include "gvaluecollector.h"
|
|
#include "gparam.h"
|
|
#include "gtype.h"
|
|
#include "gvalue.h"
|
|
#include "gvaluetypes.h"
|
|
|
|
struct _GProperty
|
|
{
|
|
GParamSpec parent_instance;
|
|
|
|
guint flags : 15;
|
|
guint is_installed : 1;
|
|
|
|
guint16 type_size;
|
|
gint field_offset;
|
|
|
|
GQuark prop_id;
|
|
};
|
|
|
|
/* defines for the integer sub-types we don't have either in GValue
|
|
* or in the type system; we rely on GValue validation for run-time
|
|
* checks
|
|
*/
|
|
#define g_value_get_int8 g_value_get_int
|
|
#define g_value_get_int16 g_value_get_int
|
|
#define g_value_get_int32 g_value_get_int
|
|
|
|
#define g_value_get_uint8 g_value_get_uint
|
|
#define g_value_get_uint16 g_value_get_uint
|
|
#define g_value_get_uint32 g_value_get_uint
|
|
|
|
static GType g_property_default_value_key = G_TYPE_INVALID;
|
|
|
|
static GParamFlags
|
|
property_flags_to_param_flags (GPropertyFlags flags)
|
|
{
|
|
GParamFlags retval = 0;
|
|
|
|
if (flags & G_PROPERTY_READABLE)
|
|
retval |= G_PARAM_READABLE;
|
|
|
|
if (flags & G_PROPERTY_WRITABLE)
|
|
retval |= G_PARAM_WRITABLE;
|
|
|
|
if (flags & G_PROPERTY_DEPRECATED)
|
|
retval |= G_PARAM_DEPRECATED;
|
|
|
|
if (flags & G_PROPERTY_CONSTRUCT_ONLY)
|
|
retval |= (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READABLE);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static GProperty *
|
|
g_property_create (GType pspec_type,
|
|
GType value_type,
|
|
const char *name,
|
|
GPropertyFlags flags,
|
|
gssize field_offset,
|
|
gsize value_size)
|
|
{
|
|
GProperty *prop;
|
|
|
|
prop = g_param_spec_internal (pspec_type,
|
|
name, NULL, NULL,
|
|
property_flags_to_param_flags (flags));
|
|
|
|
G_PARAM_SPEC (prop)->value_type = value_type;
|
|
|
|
prop->flags = flags;
|
|
prop->field_offset = field_offset;
|
|
prop->type_size = value_size;
|
|
prop->is_installed = FALSE;
|
|
|
|
return prop;
|
|
}
|
|
|
|
static inline void
|
|
g_property_ensure_prop_id (GProperty *property)
|
|
{
|
|
char *prop_id;
|
|
|
|
if (G_LIKELY (property->prop_id != 0))
|
|
return;
|
|
|
|
prop_id = g_strconcat ("-g-property-",
|
|
G_PARAM_SPEC (property)->name,
|
|
NULL);
|
|
|
|
property->prop_id = g_quark_from_string (prop_id);
|
|
|
|
g_free (prop_id);
|
|
}
|
|
|
|
#define DEFINE_PROPERTY_INTEGER(G_t, g_t, c_t, G_T, minVal, maxVal) \
|
|
typedef struct { \
|
|
GProperty parent; \
|
|
\
|
|
c_t min_value; \
|
|
c_t max_value; \
|
|
\
|
|
GProperty##G_t##Set setter; \
|
|
GProperty##G_t##Get getter; \
|
|
} G##G_t##Property; \
|
|
\
|
|
static gint \
|
|
property_##g_t##_values_cmp (GParamSpec *pspec, \
|
|
const GValue *value_a, \
|
|
const GValue *value_b) \
|
|
{ \
|
|
c_t val_a = g_value_get_##g_t (value_a); \
|
|
c_t val_b = g_value_get_##g_t (value_b); \
|
|
\
|
|
if (val_a < val_b) \
|
|
return -1; \
|
|
\
|
|
if (val_a > val_b) \
|
|
return 1; \
|
|
\
|
|
return 0; \
|
|
} \
|
|
\
|
|
static gboolean \
|
|
property_##g_t##_validate (GParamSpec *pspec, \
|
|
GValue *value) \
|
|
{ \
|
|
G##G_t##Property *internal = (G##G_t##Property *) pspec; \
|
|
c_t oval = g_value_get_##g_t (value); \
|
|
c_t nval = oval; \
|
|
\
|
|
nval = CLAMP (nval, internal->min_value, internal->max_value); \
|
|
\
|
|
return nval != oval; \
|
|
} \
|
|
\
|
|
static void \
|
|
property_##g_t##_class_init (GParamSpecClass *klass) \
|
|
{ \
|
|
klass->value_type = G_T; \
|
|
\
|
|
klass->value_validate = property_##g_t##_validate; \
|
|
klass->values_cmp = property_##g_t##_values_cmp; \
|
|
} \
|
|
\
|
|
static void \
|
|
property_##g_t##_init (GParamSpec *pspec) \
|
|
{ \
|
|
G##G_t##Property *property = (G##G_t##Property *) pspec; \
|
|
\
|
|
property->min_value = minVal; \
|
|
property->max_value = maxVal; \
|
|
} \
|
|
\
|
|
GType _g_##g_t##_property_get_type (void); /* forward declaration for -Wmissing-prototypes */ \
|
|
\
|
|
GType \
|
|
_g_##g_t##_property_get_type (void) \
|
|
{ \
|
|
static volatile gsize pspec_type_id__volatile = 0; \
|
|
\
|
|
if (g_once_init_enter (&pspec_type_id__volatile)) \
|
|
{ \
|
|
const GTypeInfo info = { \
|
|
sizeof (GParamSpecClass), \
|
|
NULL, NULL, \
|
|
(GClassInitFunc) property_##g_t##_class_init, \
|
|
NULL, NULL, \
|
|
sizeof (G##G_t##Property), \
|
|
0, \
|
|
(GInstanceInitFunc) property_##g_t##_init, \
|
|
}; \
|
|
\
|
|
GType pspec_type_id = \
|
|
g_type_register_static (G_TYPE_PROPERTY, \
|
|
g_intern_static_string ("G" #G_t "Property"), \
|
|
&info, 0); \
|
|
\
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id); \
|
|
} \
|
|
\
|
|
return pspec_type_id__volatile; \
|
|
} \
|
|
\
|
|
GParamSpec * \
|
|
g_##g_t##_property_new (const gchar *name, \
|
|
GPropertyFlags flags, \
|
|
gssize offset, \
|
|
GProperty##G_t##Set setter, \
|
|
GProperty##G_t##Get getter) \
|
|
{ \
|
|
GProperty *prop; \
|
|
G##G_t##Property *internal; \
|
|
\
|
|
g_return_val_if_fail (name != NULL, NULL); \
|
|
\
|
|
if (setter == NULL && getter == NULL) \
|
|
g_return_val_if_fail (offset != 0, NULL); \
|
|
\
|
|
prop = g_property_create (_g_##g_t##_property_get_type (), \
|
|
G_T, \
|
|
name, \
|
|
flags, \
|
|
offset, \
|
|
sizeof (c_t)); \
|
|
\
|
|
internal = (G##G_t##Property *) prop; \
|
|
internal->setter = setter; \
|
|
internal->getter = getter; \
|
|
\
|
|
return G_PARAM_SPEC (prop); \
|
|
} \
|
|
\
|
|
static inline void \
|
|
g_##g_t##_property_set_range (GProperty *property, \
|
|
c_t min_value, \
|
|
c_t max_value) \
|
|
{ \
|
|
if (min_value > max_value) \
|
|
{ \
|
|
g_critical (G_STRLOC ": Invalid range for " #g_t " property '%s'", \
|
|
G_PARAM_SPEC (property)->name); \
|
|
return; \
|
|
} \
|
|
\
|
|
((G##G_t##Property *) property)->min_value = min_value; \
|
|
((G##G_t##Property *) property)->max_value = max_value; \
|
|
} \
|
|
\
|
|
static inline void \
|
|
g_##g_t##_property_get_range (GProperty *property, \
|
|
c_t *min_value, \
|
|
c_t *max_value) \
|
|
{ \
|
|
*min_value = ((G##G_t##Property *) property)->min_value; \
|
|
*max_value = ((G##G_t##Property *) property)->max_value; \
|
|
} \
|
|
\
|
|
static inline gboolean \
|
|
g_##g_t##_property_validate (GProperty *property, \
|
|
c_t value) \
|
|
{ \
|
|
G##G_t##Property *internal = (G##G_t##Property *) property; \
|
|
\
|
|
if (value >= internal->min_value && \
|
|
value <= internal->max_value) \
|
|
return TRUE; \
|
|
\
|
|
return FALSE; \
|
|
} \
|
|
\
|
|
static inline gboolean \
|
|
g_##g_t##_property_set_value (GProperty *property, \
|
|
gpointer gobject, \
|
|
c_t value) \
|
|
{ \
|
|
gboolean retval = FALSE; \
|
|
\
|
|
if (!g_##g_t##_property_validate (property, value)) \
|
|
{ \
|
|
g_warning ("The value for the property '%s' of object '%s' is out of the valid range", \
|
|
G_PARAM_SPEC (property)->name, \
|
|
G_OBJECT_TYPE_NAME (gobject)); \
|
|
return FALSE; \
|
|
} \
|
|
\
|
|
if (((G##G_t##Property *) property)->setter != NULL) \
|
|
{ \
|
|
((G##G_t##Property *) property)->setter (gobject, value); \
|
|
\
|
|
retval = FALSE; \
|
|
} \
|
|
else if (property->field_offset != 0) \
|
|
{ \
|
|
gpointer field_p; \
|
|
\
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset); \
|
|
\
|
|
if ((* (c_t *) field_p) != value) \
|
|
{ \
|
|
(* (c_t *) field_p) = value; \
|
|
\
|
|
retval = TRUE; \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
g_critical (G_STRLOC ": No setter function or field offset specified " \
|
|
"for property '%s'", \
|
|
G_PARAM_SPEC (property)->name); \
|
|
} \
|
|
\
|
|
return retval; \
|
|
} \
|
|
\
|
|
static inline c_t \
|
|
g_##g_t##_property_get_value (GProperty *property, \
|
|
gpointer gobject) \
|
|
{ \
|
|
if (((G##G_t##Property *) property)->getter != NULL) \
|
|
{ \
|
|
return ((G##G_t##Property *) property)->getter (gobject); \
|
|
} \
|
|
else if (property->field_offset != 0) \
|
|
{ \
|
|
return G_STRUCT_MEMBER (c_t, gobject, property->field_offset); \
|
|
} \
|
|
else \
|
|
{ \
|
|
g_critical (G_STRLOC ": No setter function or field offset specified " \
|
|
"for property '%s'", \
|
|
G_PARAM_SPEC (property)->name); \
|
|
return (c_t) 0; \
|
|
} \
|
|
}
|
|
|
|
/**
|
|
* g_boolean_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a boolean value.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Boolean, boolean, gboolean, G_TYPE_BOOLEAN, FALSE, TRUE)
|
|
|
|
/**
|
|
* g_int_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an integer value.
|
|
*
|
|
* The default range of valid values is [ %G_MININT, %G_MAXINT ].
|
|
*
|
|
* If you require a specific integer size, use g_int8_property_new(),
|
|
* g_int16_property_new(), g_int32_property_new() or g_int64_property_new().
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Int, int, int, G_TYPE_INT, G_MININT, G_MAXINT)
|
|
|
|
/**
|
|
* g_int8_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an 8 bits integer value.
|
|
*
|
|
* The default range of valid values is [ %G_MININT8, %G_MAXINT8 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Int8, int8, gint8, G_TYPE_INT, G_MININT8, G_MAXINT8)
|
|
|
|
/**
|
|
* g_int16_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to a 16 bits integer value.
|
|
*
|
|
* The default range of valid values is [ %G_MININT16, %G_MAXINT16 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Int16, int16, gint16, G_TYPE_INT, G_MININT16, G_MAXINT16)
|
|
|
|
/**
|
|
* g_int32_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to a 32 bits integer value.
|
|
*
|
|
* The default range of valid values is [ %G_MININT32, %G_MAXINT32 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Int32, int32, gint32, G_TYPE_INT, G_MININT32, G_MAXINT32)
|
|
|
|
/**
|
|
* g_int64_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to a 64 bits integer value.
|
|
*
|
|
* The default range of valid values is [ %G_MININT64, %G_MAXINT64 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Int64, int64, gint64, G_TYPE_INT64, G_MININT64, G_MAXINT64)
|
|
|
|
/**
|
|
* g_long_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to a long integer value.
|
|
*
|
|
* The default range of valid values is [ %G_MINLONG, %G_MAXLONG ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (Long, long, glong, G_TYPE_LONG, G_MINLONG, G_MAXLONG)
|
|
|
|
/**
|
|
* g_uint_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an unsigned integer value.
|
|
*
|
|
* The default range of valid values is [ 0, %G_MAXUINT ].
|
|
*
|
|
* If you require a specific integer size, use g_uint8_property_new(),
|
|
* g_uint16_property_new(), g_uint32_property_new() or g_uint64_property_new().
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (UInt, uint, guint, G_TYPE_UINT, 0, G_MAXUINT)
|
|
|
|
/**
|
|
* g_uint8_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an unsigned 8 bits integer value.
|
|
*
|
|
* The default range of valid values is [ 0, %G_MAXUINT8 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (UInt8, uint8, guint8, G_TYPE_UINT, 0, G_MAXUINT8)
|
|
|
|
/**
|
|
* g_uint16_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an unsigned 16 bits integer value.
|
|
*
|
|
* The default range of valid values is [ 0, %G_MAXUINT16 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (UInt16, uint16, guint16, G_TYPE_UINT, 0, G_MAXUINT16)
|
|
|
|
/**
|
|
* g_uint32_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an unsigned 32 bits integer value.
|
|
*
|
|
* The default range of valid values is [ 0, %G_MAXUINT32 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (UInt32, uint32, guint32, G_TYPE_UINT, 0, G_MAXUINT32)
|
|
|
|
/**
|
|
* g_uint64_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an unsigned 64 bits integer value.
|
|
*
|
|
* The default range of valid values is [ 0, %G_MAXUINT64 ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (UInt64, uint64, guint64, G_TYPE_UINT64, 0, G_MAXUINT64)
|
|
|
|
/**
|
|
* g_ulong_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property, or %NULL
|
|
* @getter: (allow-none): the getter function for the property, or %NULL
|
|
*
|
|
* Creates a new #GProperty mapping to an unsigned long integer value.
|
|
*
|
|
* The default range of valid values is [ 0, %G_MAXULONG ].
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
DEFINE_PROPERTY_INTEGER (ULong, ulong, gulong, G_TYPE_ULONG, 0, G_MAXULONG)
|
|
|
|
/*
|
|
* GEnum
|
|
*/
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_enum_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
GEnumClass *e_class;
|
|
|
|
GPropertyEnumSet setter;
|
|
GPropertyEnumGet getter;
|
|
} GEnumProperty;
|
|
|
|
static gboolean
|
|
property_enum_validate (GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
GEnumProperty *property = (GEnumProperty *) pspec;
|
|
glong oval = value->data[0].v_long;
|
|
|
|
if (property->e_class == NULL ||
|
|
g_enum_get_value (property->e_class, value->data[0].v_long) == NULL)
|
|
value->data[0].v_long = 0;
|
|
|
|
return value->data[0].v_long != oval;
|
|
}
|
|
|
|
static void
|
|
property_enum_finalize (GParamSpec *pspec)
|
|
{
|
|
GEnumProperty *property = (GEnumProperty *) pspec;
|
|
GParamSpecClass *parent_class =
|
|
g_type_class_peek (g_type_parent (_g_enum_property_get_type ()));
|
|
|
|
if (property->e_class != NULL)
|
|
{
|
|
g_type_class_unref (property->e_class);
|
|
property->e_class = NULL;
|
|
}
|
|
|
|
parent_class->finalize (pspec);
|
|
}
|
|
|
|
static void
|
|
property_enum_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_FLAGS;
|
|
|
|
klass->value_validate = property_enum_validate;
|
|
|
|
klass->finalize = property_enum_finalize;
|
|
}
|
|
|
|
static void
|
|
property_enum_init (GParamSpec *pspec)
|
|
{
|
|
}
|
|
|
|
GType
|
|
_g_enum_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_enum_class_init,
|
|
NULL, NULL,
|
|
sizeof (GEnumProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_enum_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GEnumProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_enum_property_new:
|
|
* @name: canonical name of the property
|
|
* @enum: enum for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a enumeration type registered
|
|
* as a sub-type of %G_TYPE_ENUM.
|
|
*
|
|
* You must use g_property_set_prerequisite() to set the type
|
|
* of the enumeration for validation; if the pre-requisite is unset,
|
|
* setting or getting this property will result in a warning.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_enum_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyEnumSet setter,
|
|
GPropertyEnumGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GEnumProperty *internal;
|
|
|
|
prop = g_property_create (_g_enum_property_get_type (),
|
|
G_TYPE_ENUM,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (gint));
|
|
|
|
internal = (GEnumProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_enum_property_validate (GProperty *property,
|
|
gint value)
|
|
{
|
|
GEnumProperty *e_prop = (GEnumProperty *) property;
|
|
|
|
if (e_prop->e_class != NULL)
|
|
{
|
|
if (g_enum_get_value (e_prop->e_class, value) != NULL)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_enum_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
gint value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_enum_property_validate (property, value))
|
|
{
|
|
g_warning ("The enumeration value %d for the property '%s' of object '%s' is not valid",
|
|
value,
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GEnumProperty *) property)->setter != NULL)
|
|
{
|
|
((GEnumProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if ((* (gint *) field_p) != value)
|
|
{
|
|
(* (gint *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gint
|
|
g_enum_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GEnumProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GEnumProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
return G_STRUCT_MEMBER (gint, gobject, property->field_offset);
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GFlags
|
|
*/
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_flags_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
GFlagsClass *f_class;
|
|
|
|
GPropertyFlagsSet setter;
|
|
GPropertyFlagsGet getter;
|
|
} GFlagsProperty;
|
|
|
|
static gboolean
|
|
property_flags_validate (GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
GFlagsProperty *property = (GFlagsProperty *) pspec;
|
|
gulong oval = value->data[0].v_ulong;
|
|
|
|
if (property->f_class != NULL)
|
|
value->data[0].v_ulong &= property->f_class->mask;
|
|
else
|
|
value->data[0].v_ulong = 0;
|
|
|
|
return value->data[0].v_ulong != oval;
|
|
}
|
|
|
|
static void
|
|
property_flags_finalize (GParamSpec *pspec)
|
|
{
|
|
GFlagsProperty *property = (GFlagsProperty *) pspec;
|
|
GParamSpecClass *parent_class =
|
|
g_type_class_peek (g_type_parent (_g_flags_property_get_type ()));
|
|
|
|
if (property->f_class)
|
|
{
|
|
g_type_class_unref (property->f_class);
|
|
property->f_class = NULL;
|
|
}
|
|
|
|
parent_class->finalize (pspec);
|
|
}
|
|
|
|
static void
|
|
property_flags_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_FLAGS;
|
|
|
|
klass->value_validate = property_flags_validate;
|
|
|
|
klass->finalize = property_flags_finalize;
|
|
}
|
|
|
|
static void
|
|
property_flags_init (GParamSpec *pspec)
|
|
{
|
|
}
|
|
|
|
GType
|
|
_g_flags_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_flags_class_init,
|
|
NULL, NULL,
|
|
sizeof (GFlagsProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_flags_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GFlagsProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_flags_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a flag type registered
|
|
* as a sub-type of %G_TYPE_FLAGS.
|
|
*
|
|
* You must use g_property_set_prerequisite() to set the type
|
|
* of the flags for validation; if the pre-requisite is unset,
|
|
* setting or getting this property will result in a warning.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_flags_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyFlagsSet setter,
|
|
GPropertyFlagsGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GFlagsProperty *internal;
|
|
|
|
prop = g_property_create (_g_flags_property_get_type (),
|
|
G_TYPE_FLAGS,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (guint));
|
|
|
|
internal = (GFlagsProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_flags_property_validate (GProperty *property,
|
|
gulong value)
|
|
{
|
|
GFlagsProperty *f_prop = (GFlagsProperty *) property;
|
|
|
|
if (f_prop->f_class != NULL)
|
|
{
|
|
gulong masked_value = value;
|
|
|
|
masked_value &= f_prop->f_class->mask;
|
|
|
|
return masked_value == value;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_flags_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
guint value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_flags_property_validate (property, value))
|
|
{
|
|
g_warning ("The enumeration value %u for the property '%s' of object '%s' is not valid",
|
|
value,
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GFlagsProperty *) property)->setter != NULL)
|
|
{
|
|
((GFlagsProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if ((* (guint *) field_p) != value)
|
|
{
|
|
(* (guint *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline guint
|
|
g_flags_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GFlagsProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GFlagsProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
return G_STRUCT_MEMBER (guint, gobject, property->field_offset);
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GFloat
|
|
*/
|
|
|
|
#define G_FLOAT_EPSILON (1e-30)
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_float_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
gfloat min_value;
|
|
gfloat max_value;
|
|
gfloat epsilon;
|
|
|
|
GPropertyFloatSet setter;
|
|
GPropertyFloatGet getter;
|
|
} GFloatProperty;
|
|
|
|
static gboolean
|
|
property_float_validate (GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
GFloatProperty *property = (GFloatProperty *) pspec;
|
|
gfloat oval = value->data[0].v_float;
|
|
|
|
value->data[0].v_float = CLAMP (value->data[0].v_float,
|
|
property->min_value,
|
|
property->max_value);
|
|
|
|
return value->data[0].v_float != oval;
|
|
}
|
|
|
|
static gint
|
|
property_float_values_cmp (GParamSpec *pspec,
|
|
const GValue *value1,
|
|
const GValue *value2)
|
|
{
|
|
gfloat epsilon = ((GFloatProperty *) pspec)->epsilon;
|
|
|
|
if (value1->data[0].v_float < value2->data[0].v_float)
|
|
return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
|
|
else
|
|
return value1->data[0].v_float - value2->data[0].v_float > epsilon;
|
|
}
|
|
|
|
static void
|
|
property_float_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_FLOAT;
|
|
|
|
klass->value_validate = property_float_validate;
|
|
klass->values_cmp = property_float_values_cmp;
|
|
}
|
|
|
|
static void
|
|
property_float_init (GParamSpec *pspec)
|
|
{
|
|
GFloatProperty *property = (GFloatProperty *) pspec;
|
|
|
|
property->min_value = -G_MAXFLOAT;
|
|
property->max_value = G_MAXFLOAT;
|
|
property->epsilon = G_FLOAT_EPSILON;
|
|
}
|
|
|
|
GType
|
|
_g_float_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_float_class_init,
|
|
NULL, NULL,
|
|
sizeof (GFloatProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_float_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GFloatProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_float_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a single precision floating
|
|
* point value.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_float_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyFloatSet setter,
|
|
GPropertyFloatGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GFloatProperty *internal;
|
|
|
|
prop = g_property_create (_g_float_property_get_type (),
|
|
G_TYPE_FLOAT,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (float));
|
|
|
|
internal = (GFloatProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline void
|
|
g_float_property_set_range (GProperty *property,
|
|
gfloat min_value,
|
|
gfloat max_value)
|
|
{
|
|
if (min_value > max_value)
|
|
{
|
|
g_critical (G_STRLOC ": Invalid range for the property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return;
|
|
}
|
|
|
|
((GFloatProperty *) property)->min_value = min_value;
|
|
((GFloatProperty *) property)->max_value = max_value;
|
|
}
|
|
|
|
static inline void
|
|
g_float_property_get_range (GProperty *property,
|
|
gfloat *min_value,
|
|
gfloat *max_value)
|
|
{
|
|
*min_value = ((GFloatProperty *) property)->min_value;
|
|
*max_value = ((GFloatProperty *) property)->max_value;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_float_property_validate (GProperty *property,
|
|
gfloat value)
|
|
{
|
|
GFloatProperty *internal = (GFloatProperty *) property;
|
|
|
|
if (value >= internal->min_value &&
|
|
value <= internal->max_value)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_float_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
gfloat value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_float_property_validate (property, value))
|
|
{
|
|
g_warning ("The value '%f' for the property '%s' of object '%s' is outside of the allowed range",
|
|
value,
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GFloatProperty *) property)->setter != NULL)
|
|
{
|
|
((GFloatProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if ((* (gfloat *) field_p) != value)
|
|
{
|
|
(* (gfloat *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gfloat
|
|
g_float_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GFloatProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GFloatProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
return G_STRUCT_MEMBER (gfloat, gobject, property->field_offset);
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GDouble
|
|
*/
|
|
|
|
#define G_DOUBLE_EPSILON (1e-90)
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_double_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
gdouble min_value;
|
|
gdouble max_value;
|
|
gdouble epsilon;
|
|
|
|
GPropertyDoubleSet setter;
|
|
GPropertyDoubleGet getter;
|
|
} GDoubleProperty;
|
|
|
|
static gboolean
|
|
property_double_validate (GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
GDoubleProperty *property = (GDoubleProperty *) pspec;
|
|
gdouble oval = value->data[0].v_double;
|
|
|
|
value->data[0].v_double = CLAMP (value->data[0].v_double,
|
|
property->min_value,
|
|
property->max_value);
|
|
|
|
return value->data[0].v_double != oval;
|
|
}
|
|
|
|
static gint
|
|
property_double_values_cmp (GParamSpec *pspec,
|
|
const GValue *value1,
|
|
const GValue *value2)
|
|
{
|
|
gdouble epsilon = ((GDoubleProperty *) pspec)->epsilon;
|
|
|
|
if (value1->data[0].v_double < value2->data[0].v_double)
|
|
return - (value2->data[0].v_double - value1->data[0].v_double > epsilon);
|
|
else
|
|
return value1->data[0].v_double - value2->data[0].v_double > epsilon;
|
|
}
|
|
|
|
static void
|
|
property_double_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_DOUBLE;
|
|
|
|
klass->value_validate = property_double_validate;
|
|
klass->values_cmp = property_double_values_cmp;
|
|
}
|
|
|
|
static void
|
|
property_double_init (GParamSpec *pspec)
|
|
{
|
|
GDoubleProperty *property = (GDoubleProperty *) pspec;
|
|
|
|
property->min_value = -G_MAXDOUBLE;
|
|
property->max_value = G_MAXDOUBLE;
|
|
property->epsilon = G_DOUBLE_EPSILON;
|
|
}
|
|
|
|
GType
|
|
_g_double_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_double_class_init,
|
|
NULL, NULL,
|
|
sizeof (GDoubleProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_double_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GDoubleProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_double_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a double precision floating
|
|
* point value.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_double_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyDoubleSet setter,
|
|
GPropertyDoubleGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GDoubleProperty *internal;
|
|
|
|
prop = g_property_create (_g_double_property_get_type (),
|
|
G_TYPE_DOUBLE,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (double));
|
|
|
|
internal = (GDoubleProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline void
|
|
g_double_property_set_range (GProperty *property,
|
|
gdouble min_value,
|
|
gdouble max_value)
|
|
{
|
|
if (min_value > max_value)
|
|
{
|
|
g_critical (G_STRLOC ": Invalid range for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return;
|
|
}
|
|
|
|
((GDoubleProperty *) property)->min_value = min_value;
|
|
((GDoubleProperty *) property)->max_value = max_value;
|
|
}
|
|
|
|
static inline void
|
|
g_double_property_get_range (GProperty *property,
|
|
gdouble *min_value,
|
|
gdouble *max_value)
|
|
{
|
|
*min_value = ((GDoubleProperty *) property)->min_value;
|
|
*max_value = ((GDoubleProperty *) property)->max_value;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_double_property_validate (GProperty *property,
|
|
gdouble value)
|
|
{
|
|
GDoubleProperty *internal = (GDoubleProperty *) property;
|
|
|
|
if (value >= internal->min_value &&
|
|
value <= internal->max_value)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_double_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
gdouble value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_double_property_validate (property, value))
|
|
{
|
|
g_warning ("The value '%g' for the property '%s' of object '%s' is outside of the allowed range",
|
|
value,
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GDoubleProperty *) property)->setter != NULL)
|
|
{
|
|
((GDoubleProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if ((* (gdouble *) field_p) != value)
|
|
{
|
|
(* (gdouble *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gdouble
|
|
g_double_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GDoubleProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GDoubleProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
return G_STRUCT_MEMBER (gdouble, gobject, property->field_offset);
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GString
|
|
*/
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_string_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
GPropertyStringSet setter;
|
|
GPropertyStringGet getter;
|
|
} GStringProperty;
|
|
|
|
static void
|
|
property_string_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_STRING;
|
|
}
|
|
|
|
static void
|
|
property_string_init (GParamSpec *pspec)
|
|
{
|
|
}
|
|
|
|
GType
|
|
_g_string_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_string_class_init,
|
|
NULL, NULL,
|
|
sizeof (GStringProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_string_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GStringProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_string_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a string value.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_string_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyStringSet setter,
|
|
GPropertyStringGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GStringProperty *internal;
|
|
|
|
prop = g_property_create (_g_string_property_get_type (),
|
|
G_TYPE_STRING,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (char *));
|
|
|
|
internal = (GStringProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_string_property_validate (GProperty *property,
|
|
const gchar *value)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_string_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
const gchar *value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_string_property_validate (property, value))
|
|
{
|
|
g_warning ("The value '%s' for the property '%s' of object '%s' is not valid",
|
|
value,
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GStringProperty *) property)->setter != NULL)
|
|
{
|
|
((GStringProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
gchar *str;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
str = (* (gpointer *) field_p);
|
|
|
|
if (g_strcmp0 (str, value) == 0)
|
|
return FALSE;
|
|
|
|
if (property->flags & G_PROPERTY_COPY_SET)
|
|
{
|
|
g_free (str);
|
|
(* (gpointer *) field_p) = g_strdup (value);
|
|
}
|
|
else
|
|
(* (gpointer *) field_p) = (gpointer) value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline const gchar *
|
|
g_string_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GStringProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GStringProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
gchar *retval;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if (property->flags & G_PROPERTY_COPY_GET)
|
|
retval = g_strdup ((* (gpointer *) field_p));
|
|
else
|
|
retval = (* (gpointer *) field_p);
|
|
|
|
return retval;
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GBoxed
|
|
*/
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_boxed_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
GPropertyBoxedSet setter;
|
|
GPropertyBoxedGet getter;
|
|
} GBoxedProperty;
|
|
|
|
static void
|
|
property_boxed_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_BOXED;
|
|
}
|
|
|
|
static void
|
|
property_boxed_init (GParamSpec *pspec)
|
|
{
|
|
}
|
|
|
|
GType
|
|
_g_boxed_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_boxed_class_init,
|
|
NULL, NULL,
|
|
sizeof (GBoxedProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_boxed_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GBoxedProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_boxed_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to a boxed value.
|
|
*
|
|
* You must use g_property_set_prerequisite() to specify the #GType
|
|
* of the boxed value, otherwise setting or getting this property
|
|
* will result in a warning.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_boxed_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyBoxedSet setter,
|
|
GPropertyBoxedGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GBoxedProperty *internal;
|
|
|
|
prop = g_property_create (_g_boxed_property_get_type (),
|
|
G_TYPE_BOXED,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (gpointer));
|
|
|
|
internal = (GBoxedProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_boxed_property_validate (GProperty *property,
|
|
gconstpointer value)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_boxed_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
gpointer value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_boxed_property_validate (property, value))
|
|
{
|
|
g_warning ("The value for the property '%s' of object '%s' is not valid",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GBoxedProperty *) property)->setter != NULL)
|
|
{
|
|
((GBoxedProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
gpointer old_value;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if (property->flags & G_PROPERTY_COPY_SET)
|
|
{
|
|
old_value = (* (gpointer *) field_p);
|
|
|
|
if (value != NULL)
|
|
(* (gpointer *) field_p) = g_boxed_copy (((GParamSpec *) property)->value_type, value);
|
|
else
|
|
(* (gpointer *) field_p) = NULL;
|
|
|
|
if (old_value != NULL)
|
|
g_boxed_free (((GParamSpec *) property)->value_type, old_value);
|
|
}
|
|
else
|
|
(* (gpointer *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gpointer
|
|
g_boxed_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GBoxedProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GBoxedProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
gpointer value;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if (property->flags & G_PROPERTY_COPY_GET)
|
|
value = g_boxed_copy (((GParamSpec *) property)->value_type, (* (gpointer *) field_p));
|
|
else
|
|
value = (* (gpointer *) field_p);
|
|
|
|
return value;
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GObject
|
|
*/
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_object_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
GPropertyObjectSet setter;
|
|
GPropertyObjectGet getter;
|
|
} GObjectProperty;
|
|
|
|
static void
|
|
property_object_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_OBJECT;
|
|
}
|
|
|
|
static void
|
|
property_object_init (GParamSpec *pspec)
|
|
{
|
|
}
|
|
|
|
GType
|
|
_g_object_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_object_class_init,
|
|
NULL, NULL,
|
|
sizeof (GObjectProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_object_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GObjectProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_object_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to an object value.
|
|
*
|
|
* You can use g_property_set_prerequisite() to restrict the #GType
|
|
* of the object value to a specific sub-class of #GObject.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_object_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyObjectSet setter,
|
|
GPropertyObjectGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GObjectProperty *internal;
|
|
|
|
prop = g_property_create (_g_object_property_get_type (),
|
|
G_TYPE_OBJECT,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (gpointer));
|
|
|
|
internal = (GObjectProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_object_property_validate (GProperty *property,
|
|
gconstpointer value)
|
|
{
|
|
if (value == NULL)
|
|
return FALSE;
|
|
|
|
return g_type_is_a (G_OBJECT_TYPE (value), G_PARAM_SPEC (property)->value_type);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_object_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
gpointer value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_object_property_validate (property, value))
|
|
{
|
|
g_warning ("The value for the property '%s' of object '%s' is not valid",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GObjectProperty *) property)->setter != NULL)
|
|
{
|
|
((GObjectProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
gpointer obj;
|
|
|
|
g_return_val_if_fail (value == NULL || G_IS_OBJECT (value), FALSE);
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if ((* (gpointer *) field_p) == value)
|
|
return FALSE;
|
|
|
|
if (property->flags & G_PROPERTY_COPY_SET)
|
|
{
|
|
obj = (* (gpointer *) field_p);
|
|
if (obj != NULL)
|
|
g_object_unref (obj);
|
|
|
|
(* (gpointer *) field_p) = obj = value;
|
|
|
|
if (obj != NULL)
|
|
{
|
|
if (G_IS_INITIALLY_UNOWNED (obj))
|
|
g_object_ref_sink (obj);
|
|
else
|
|
g_object_ref (obj);
|
|
}
|
|
}
|
|
else
|
|
(* (gpointer *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gpointer
|
|
g_object_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GObjectProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GObjectProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
GObject *obj;
|
|
|
|
obj = &G_STRUCT_MEMBER (GObject, gobject, property->field_offset);
|
|
|
|
if (property->flags & G_PROPERTY_COPY_GET)
|
|
{
|
|
if (obj != NULL)
|
|
return g_object_ref (obj);
|
|
else
|
|
return NULL;
|
|
}
|
|
else
|
|
return obj;
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* gpointer
|
|
*/
|
|
|
|
/* forward declaration for -Wmissing-prototypes */
|
|
GType _g_pointer_property_get_type (void);
|
|
|
|
typedef struct {
|
|
GProperty parent;
|
|
|
|
GPropertyPointerSet setter;
|
|
GPropertyPointerGet getter;
|
|
} GPointerProperty;
|
|
|
|
static void
|
|
property_pointer_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_POINTER;
|
|
}
|
|
|
|
static void
|
|
property_pointer_init (GParamSpec *pspec)
|
|
{
|
|
}
|
|
|
|
GType
|
|
_g_pointer_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_pointer_class_init,
|
|
NULL, NULL,
|
|
sizeof (GPointerProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_pointer_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PROPERTY,
|
|
g_intern_static_string ("GPointerProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|
|
|
|
/**
|
|
* g_pointer_property_new:
|
|
* @name: canonical name of the property
|
|
* @flags: flags for the property
|
|
* @offset: the offset in the private structure of the field
|
|
* that stores the property, or -1
|
|
* @setter: (allow-none): the setter function for the property
|
|
* @getter: (allow-none): the getter function for the property
|
|
*
|
|
* Creates a new #GProperty mapping to an untyped pointer.
|
|
*
|
|
* Return value: the newly created #GProperty
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GParamSpec *
|
|
g_pointer_property_new (const gchar *name,
|
|
GPropertyFlags flags,
|
|
gssize offset,
|
|
GPropertyObjectSet setter,
|
|
GPropertyObjectGet getter)
|
|
{
|
|
GProperty *prop;
|
|
GPointerProperty *internal;
|
|
|
|
prop = g_property_create (_g_pointer_property_get_type (),
|
|
G_TYPE_POINTER,
|
|
name,
|
|
flags,
|
|
offset,
|
|
sizeof (gpointer));
|
|
|
|
internal = (GPointerProperty *) prop;
|
|
internal->setter = setter;
|
|
internal->getter = getter;
|
|
|
|
return G_PARAM_SPEC (prop);
|
|
}
|
|
|
|
static inline gboolean
|
|
g_pointer_property_validate (GProperty *property,
|
|
gconstpointer value)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_pointer_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
gpointer value)
|
|
{
|
|
gboolean retval = FALSE;
|
|
|
|
if (!g_pointer_property_validate (property, value))
|
|
{
|
|
g_warning ("The value for the property '%s' of object '%s' is not valid",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
if (((GPointerProperty *) property)->setter != NULL)
|
|
{
|
|
((GPointerProperty *) property)->setter (gobject, value);
|
|
|
|
retval = FALSE;
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
gpointer field_p;
|
|
|
|
field_p = G_STRUCT_MEMBER_P (gobject, property->field_offset);
|
|
|
|
if ((* (gpointer *) field_p) != value)
|
|
{
|
|
(* (gpointer *) field_p) = value;
|
|
|
|
retval = TRUE;
|
|
}
|
|
}
|
|
else
|
|
g_critical (G_STRLOC ": No setter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gpointer
|
|
g_pointer_property_get_value (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
if (((GPointerProperty *) property)->getter != NULL)
|
|
{
|
|
return ((GPointerProperty *) property)->getter (gobject);
|
|
}
|
|
else if (property->field_offset != 0)
|
|
{
|
|
return G_STRUCT_MEMBER (gpointer, gobject, property->field_offset);
|
|
}
|
|
else
|
|
{
|
|
g_critical (G_STRLOC ": No getter function or field offset specified "
|
|
"for property '%s'",
|
|
G_PARAM_SPEC (property)->name);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* GProperty common API
|
|
*/
|
|
|
|
/*< private >
|
|
* g_property_set_installed:
|
|
* @property: a #GProperty
|
|
* @class_gtype: the #GType of the class that installed @property
|
|
*
|
|
* Performs additional work once a type class has been associated to
|
|
* the property.
|
|
*/
|
|
void
|
|
g_property_set_installed (GProperty *property,
|
|
gpointer g_class,
|
|
GType class_gtype)
|
|
{
|
|
if (property->field_offset != 0)
|
|
{
|
|
gboolean is_interface = G_TYPE_IS_INTERFACE (class_gtype);
|
|
|
|
if (G_UNLIKELY (is_interface))
|
|
{
|
|
g_critical (G_STRLOC ": The property '%s' has a field offset value "
|
|
"but it is being installed on an interface of type '%s'. "
|
|
"Properties installed on interfaces cannot have direct "
|
|
"access to a structure field.",
|
|
G_PARAM_SPEC (property)->name,
|
|
g_type_name (class_gtype));
|
|
|
|
property->field_offset = 0;
|
|
}
|
|
}
|
|
|
|
g_property_ensure_prop_id (property);
|
|
|
|
property->is_installed = TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
is_canonical (const gchar *key)
|
|
{
|
|
const gchar *p;
|
|
|
|
for (p = key; *p != 0; p++)
|
|
{
|
|
gchar c = *p;
|
|
|
|
if (c != '-' &&
|
|
(c < '0' || c > '9') &&
|
|
(c < 'A' || c > 'Z') &&
|
|
(c < 'a' || c > 'z'))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
canonicalize_name (gchar *key)
|
|
{
|
|
gchar *p;
|
|
|
|
for (p = key; *p != 0; p++)
|
|
{
|
|
gchar c = *p;
|
|
|
|
if (c != '-' &&
|
|
(c < '0' || c > '9') &&
|
|
(c < 'A' || c > 'Z') &&
|
|
(c < 'a' || c > 'z'))
|
|
*p = '-';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* g_property_canonicalize_name:
|
|
* @name: a string
|
|
*
|
|
* Canonicalizes a string into a property name.
|
|
*
|
|
* Return value: (transfer none): the canonical version of @name.
|
|
* The returned string is owned by GLib and it should not be
|
|
* modified or freed
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
const gchar *
|
|
g_property_canonicalize_name (const gchar *name)
|
|
{
|
|
gchar *canonicalized;
|
|
const gchar *retval;
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
|
|
if (is_canonical (name))
|
|
return g_intern_string (name);
|
|
|
|
canonicalized = g_strdup (name);
|
|
canonicalize_name (canonicalized);
|
|
retval = g_intern_string (canonicalized);
|
|
g_free (canonicalized);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* g_property_set_prerequisite:
|
|
* @property: a #GProperty
|
|
* @...: the prerequisite type
|
|
*
|
|
* Sets the prerequisite type for #GProperty storing a classed type,
|
|
* like #GObject, #GBoxed, #GEnum, and #GFlags.
|
|
*
|
|
* The prerequisite type must have the @property GType as a super-type,
|
|
* and will be used to make the type check stricter.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_set_prerequisite (GProperty *property,
|
|
...)
|
|
{
|
|
va_list args;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
|
|
va_start (args, property);
|
|
|
|
switch (G_PARAM_SPEC (property)->value_type)
|
|
{
|
|
case G_TYPE_BOXED:
|
|
case G_TYPE_OBJECT:
|
|
{
|
|
GType gtype;
|
|
|
|
gtype = va_arg (args, GType);
|
|
g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
|
|
g_return_if_fail (g_type_is_a (gtype, G_PARAM_SPEC (property)->value_type));
|
|
G_PARAM_SPEC (property)->value_type = gtype;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
{
|
|
GType gtype;
|
|
|
|
gtype = va_arg (args, GType);
|
|
G_PARAM_SPEC (property)->value_type = gtype;
|
|
((GEnumProperty *) property)->e_class = g_type_class_ref (gtype);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
{
|
|
GType gtype;
|
|
|
|
gtype = va_arg (args, GType);
|
|
G_PARAM_SPEC (property)->value_type = gtype;
|
|
((GFlagsProperty *) property)->f_class = g_type_class_ref (gtype);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
va_end (args);
|
|
}
|
|
|
|
/**
|
|
* g_property_set_range_values:
|
|
* @property: a #GProperty
|
|
* @min_value: a #GValue with the minimum value of the range
|
|
* @max_value: a #GValue with the maximum value of the range
|
|
*
|
|
* Sets the valid range of @property, using #GValue<!-- -->s.
|
|
*
|
|
* This function is intended for language bindings.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_set_range_values (GProperty *property,
|
|
const GValue *min_value,
|
|
const GValue *max_value)
|
|
{
|
|
GType gtype;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
|
|
g_return_if_fail (!property->is_installed);
|
|
g_return_if_fail (min_value != NULL && max_value != NULL);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (min_value), gtype));
|
|
g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (max_value), gtype));
|
|
|
|
switch (gtype)
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
g_boolean_property_set_range (property,
|
|
g_value_get_boolean (min_value),
|
|
g_value_get_boolean (max_value));
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
gint min_v = g_value_get_int (min_value);
|
|
gint max_v = g_value_get_int (max_value);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_int8_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 2:
|
|
g_int16_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 4:
|
|
g_int32_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
default:
|
|
g_int_property_set_range (property, min_v, max_v);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
g_int64_property_set_range (property,
|
|
g_value_get_int64 (min_value),
|
|
g_value_get_int64 (max_value));
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
g_long_property_set_range (property,
|
|
g_value_get_long (min_value),
|
|
g_value_get_long (max_value));
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
guint min_v = g_value_get_uint (min_value);
|
|
guint max_v = g_value_get_uint (max_value);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_uint8_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 2:
|
|
g_uint16_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 4:
|
|
g_uint32_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
default:
|
|
g_uint_property_set_range (property, min_v, max_v);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
g_uint64_property_set_range (property,
|
|
g_value_get_uint64 (min_value),
|
|
g_value_get_uint64 (max_value));
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
g_ulong_property_set_range (property,
|
|
g_value_get_ulong (min_value),
|
|
g_value_get_ulong (max_value));
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
g_float_property_set_range (property,
|
|
g_value_get_float (min_value),
|
|
g_value_get_float (max_value));
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
g_double_property_set_range (property,
|
|
g_value_get_double (min_value),
|
|
g_value_get_double (max_value));
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* g_property_get_range_values:
|
|
* @property: a #GProperty
|
|
* @min_value: a #GValue
|
|
* @max_value: a #GValue
|
|
*
|
|
* Retrieves the bounds of the range of valid values for @property
|
|
* and stores them into @min_value and @max_value. If the passed
|
|
* #GValues have not been initialized, this function will initialize
|
|
* them to the type of the @property.
|
|
*
|
|
* Return value: %TRUE if successful, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_get_range_values (GProperty *property,
|
|
GValue *min_value,
|
|
GValue *max_value)
|
|
{
|
|
gboolean retval;
|
|
GType gtype;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
g_return_val_if_fail (min_value != NULL, FALSE);
|
|
g_return_val_if_fail (max_value != NULL, FALSE);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
if (G_VALUE_TYPE (min_value) == G_TYPE_INVALID)
|
|
g_value_init (min_value, gtype);
|
|
else
|
|
g_return_val_if_fail (g_value_type_compatible (gtype, G_VALUE_TYPE (min_value)), FALSE);
|
|
|
|
if (G_VALUE_TYPE (max_value) == G_TYPE_INVALID)
|
|
g_value_init (max_value, gtype);
|
|
else
|
|
g_return_val_if_fail (g_value_type_compatible (gtype, G_VALUE_TYPE (max_value)), FALSE);
|
|
|
|
switch (gtype)
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
{
|
|
gboolean min_v, max_v;
|
|
|
|
g_boolean_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_boolean (min_value, min_v);
|
|
g_value_set_boolean (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
gint min_v, max_v;
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_int8_property_get_range (property, (gint8 *) &min_v, (gint8 *) &max_v);
|
|
break;
|
|
|
|
case 2:
|
|
g_int16_property_get_range (property, (gint16 *) &min_v, (gint16 *) &max_v);
|
|
break;
|
|
|
|
case 4:
|
|
g_int32_property_get_range (property, (gint32 *) &min_v, (gint32 *) &max_v);
|
|
break;
|
|
|
|
default:
|
|
g_int_property_get_range (property, &min_v, &max_v);
|
|
break;
|
|
}
|
|
|
|
g_value_set_int (min_value, min_v);
|
|
g_value_set_int (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
{
|
|
gint64 min_v, max_v;
|
|
|
|
g_int64_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_int64 (min_value, min_v);
|
|
g_value_set_int64 (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
{
|
|
glong min_v, max_v;
|
|
|
|
g_long_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_long (min_value, min_v);
|
|
g_value_set_long (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
guint min_v, max_v;
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_uint8_property_get_range (property, (guint8 *) &min_v, (guint8 *) &max_v);
|
|
break;
|
|
|
|
case 2:
|
|
g_uint16_property_get_range (property, (guint16 *) &min_v, (guint16 *) &max_v);
|
|
break;
|
|
|
|
case 4:
|
|
g_uint32_property_get_range (property, (guint32 *) &min_v, (guint32 *) &max_v);
|
|
break;
|
|
|
|
default:
|
|
g_uint_property_get_range (property, &min_v, &max_v);
|
|
break;
|
|
}
|
|
|
|
g_value_set_uint (min_value, min_v);
|
|
g_value_set_uint (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
{
|
|
guint64 min_v, max_v;
|
|
|
|
g_uint64_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_uint64 (min_value, min_v);
|
|
g_value_set_uint64 (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
{
|
|
gulong min_v, max_v;
|
|
|
|
g_ulong_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_ulong (min_value, min_v);
|
|
g_value_set_ulong (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
{
|
|
gfloat min_v, max_v;
|
|
|
|
g_float_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_float (min_value, min_v);
|
|
g_value_set_float (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
{
|
|
gdouble min_v, max_v;
|
|
|
|
g_double_property_get_range (property, &min_v, &max_v);
|
|
g_value_set_double (min_value, min_v);
|
|
g_value_set_double (max_value, max_v);
|
|
}
|
|
retval = TRUE;
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type '%s'", g_type_name (gtype));
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* g_property_set_range:
|
|
* @property: a #GProperty
|
|
* @...: the minimum and maximum values of the range
|
|
*
|
|
* Sets the range of valid values for @property.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_set_range (GProperty *property,
|
|
...)
|
|
{
|
|
GType gtype;
|
|
va_list args;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (!property->is_installed);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
g_return_if_fail (gtype != G_TYPE_INVALID);
|
|
|
|
va_start (args, property);
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
{
|
|
gboolean min_v = va_arg (args, gboolean);
|
|
gboolean max_v = va_arg (args, gboolean);
|
|
|
|
g_boolean_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
gint min_v = va_arg (args, gint);
|
|
gint max_v = va_arg (args, gint);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_int8_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 2:
|
|
g_int16_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 4:
|
|
g_int32_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
default:
|
|
g_int_property_set_range (property, min_v, max_v);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
{
|
|
gint64 min_v = va_arg (args, gint64);
|
|
gint64 max_v = va_arg (args, gint64);
|
|
|
|
g_int64_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
{
|
|
glong min_v = va_arg (args, glong);
|
|
glong max_v = va_arg (args, glong);
|
|
|
|
g_long_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
guint min_v = va_arg (args, guint);
|
|
guint max_v = va_arg (args, guint);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_uint8_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 2:
|
|
g_uint16_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
case 4:
|
|
g_uint32_property_set_range (property, min_v, max_v);
|
|
break;
|
|
|
|
default:
|
|
g_uint_property_set_range (property, min_v, max_v);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
{
|
|
guint64 min_v = va_arg (args, guint64);
|
|
guint64 max_v = va_arg (args, guint64);
|
|
|
|
g_uint64_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
{
|
|
gulong min_v = va_arg (args, gulong);
|
|
gulong max_v = va_arg (args, gulong);
|
|
|
|
g_ulong_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
{
|
|
gfloat min_v = va_arg (args, gdouble);
|
|
gfloat max_v = va_arg (args, gdouble);
|
|
|
|
g_float_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
{
|
|
gdouble min_v = va_arg (args, gdouble);
|
|
gdouble max_v = va_arg (args, gdouble);
|
|
|
|
g_double_property_set_range (property, min_v, max_v);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
}
|
|
|
|
va_end (args);
|
|
}
|
|
|
|
/**
|
|
* g_property_get_range:
|
|
* @property: a #GProperty
|
|
* @...: the return locations for the minimum and maximum values
|
|
* of the range
|
|
*
|
|
* Retrieves the bounds of the range of valid values for @property.
|
|
*
|
|
* Return value: %TRUE on success, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_get_range (GProperty *property,
|
|
...)
|
|
{
|
|
va_list var_args;
|
|
GType gtype;
|
|
gboolean retval;
|
|
gpointer min_p, max_p;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
g_return_val_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID, FALSE);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
va_start (var_args, property);
|
|
|
|
min_p = va_arg (var_args, gpointer);
|
|
max_p = va_arg (var_args, gpointer);
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
g_boolean_property_get_range (property, (gboolean *) min_p, (gboolean *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_int8_property_get_range (property, (gint8 *) min_p, (gint8 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case 2:
|
|
g_int16_property_get_range (property, (gint16 *) min_p, (gint16 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case 4:
|
|
g_int32_property_get_range (property, (gint32 *) min_p, (gint32 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
default:
|
|
g_int_property_get_range (property, (gint *) min_p, (gint *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
g_int64_property_get_range (property, (gint64 *) min_p, (gint64 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
g_long_property_get_range (property, (glong *) min_p, (glong *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
g_uint8_property_get_range (property, (guint8 *) min_p, (guint8 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case 2:
|
|
g_uint16_property_get_range (property, (guint16 *) min_p, (guint16 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case 4:
|
|
g_uint32_property_get_range (property, (guint32 *) min_p, (guint32 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
default:
|
|
g_uint_property_get_range (property, (guint *) min_p, (guint *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
g_uint64_property_get_range (property, (guint64 *) min_p, (guint64 *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
g_ulong_property_get_range (property, (gulong *) min_p, (gulong *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
g_float_property_get_range (property, (gfloat *) min_p, (gfloat *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
g_double_property_get_range (property, (gdouble *) min_p, (gdouble *) max_p);
|
|
retval = TRUE;
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
retval = FALSE;
|
|
}
|
|
|
|
va_end (var_args);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static void
|
|
value_unset_and_free (gpointer data)
|
|
{
|
|
if (G_LIKELY (data != NULL))
|
|
{
|
|
GValue *value = data;
|
|
|
|
g_value_unset (value);
|
|
g_free (value);
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
g_property_set_default_value_internal (GProperty *property,
|
|
GValue *value)
|
|
{
|
|
GHashTable *default_values;
|
|
|
|
g_property_ensure_prop_id (property);
|
|
|
|
default_values = g_param_spec_get_qdata (G_PARAM_SPEC (property),
|
|
property->prop_id);
|
|
if (default_values == NULL)
|
|
{
|
|
default_values = g_hash_table_new_full (NULL, NULL,
|
|
NULL,
|
|
value_unset_and_free);
|
|
g_param_spec_set_qdata_full (G_PARAM_SPEC (property),
|
|
property->prop_id,
|
|
default_values,
|
|
(GDestroyNotify) g_hash_table_unref);
|
|
}
|
|
|
|
g_hash_table_replace (default_values,
|
|
GSIZE_TO_POINTER (g_property_default_value_key),
|
|
value);
|
|
}
|
|
|
|
static inline const GValue *
|
|
g_property_get_default_value_internal (GProperty *property,
|
|
GType gtype)
|
|
{
|
|
GHashTable *default_values;
|
|
const GValue *default_value = NULL;
|
|
GType iter;
|
|
|
|
if (property->prop_id == 0)
|
|
return NULL;
|
|
|
|
default_values = g_param_spec_get_qdata (G_PARAM_SPEC (property),
|
|
property->prop_id);
|
|
if (default_values == NULL)
|
|
return NULL;
|
|
|
|
/* we look for overridden default values on ourselves and our parent
|
|
* classes first...*/
|
|
iter = gtype;
|
|
while (iter != G_TYPE_INVALID && default_value == NULL)
|
|
{
|
|
default_value = g_hash_table_lookup (default_values, GSIZE_TO_POINTER (iter));
|
|
|
|
iter = g_type_parent (iter);
|
|
}
|
|
|
|
/* ...as well as on our interfaces... */
|
|
if (default_value == NULL)
|
|
{
|
|
GType *ifaces = NULL;
|
|
guint n_ifaces = 0;
|
|
|
|
ifaces = g_type_interfaces (gtype, &n_ifaces);
|
|
while (n_ifaces-- && default_value == NULL)
|
|
{
|
|
iter = ifaces[n_ifaces];
|
|
default_value = g_hash_table_lookup (default_values, GSIZE_TO_POINTER (iter));
|
|
}
|
|
|
|
g_free (ifaces);
|
|
}
|
|
|
|
/* ...and if we fail, we pick the default value set by the class that
|
|
* installed the property first
|
|
*/
|
|
if (default_value == NULL)
|
|
{
|
|
default_value = g_hash_table_lookup (default_values, GSIZE_TO_POINTER (g_property_default_value_key));
|
|
}
|
|
|
|
return default_value;
|
|
}
|
|
|
|
static inline void
|
|
g_property_override_default_value_internal (GProperty *property,
|
|
GType class_type,
|
|
GValue *value)
|
|
{
|
|
GHashTable *default_values;
|
|
|
|
g_property_ensure_prop_id (property);
|
|
|
|
default_values = g_param_spec_get_qdata (G_PARAM_SPEC (property),
|
|
property->prop_id);
|
|
if (default_values == NULL)
|
|
{
|
|
default_values = g_hash_table_new_full (NULL, NULL,
|
|
NULL,
|
|
value_unset_and_free);
|
|
g_param_spec_set_qdata_full (G_PARAM_SPEC (property),
|
|
property->prop_id,
|
|
default_values,
|
|
(GDestroyNotify) g_hash_table_unref);
|
|
}
|
|
|
|
g_hash_table_replace (default_values,
|
|
GSIZE_TO_POINTER (class_type),
|
|
value);
|
|
}
|
|
|
|
/**
|
|
* g_property_set_default_value:
|
|
* @property: a #GProperty
|
|
* @value: the default value of the property
|
|
*
|
|
* Sets the default value of @property using @value.
|
|
*
|
|
* This function will copy the passed #GValue, transforming it into the
|
|
* type required by the @property using the #GValue transformation rules
|
|
* if necessary.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_set_default_value (GProperty *property,
|
|
const GValue *value)
|
|
{
|
|
GValue *default_value;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (value != NULL);
|
|
|
|
default_value = g_new0 (GValue, 1);
|
|
g_value_init (default_value, G_PARAM_SPEC (property)->value_type);
|
|
|
|
if (!g_value_transform (value, default_value))
|
|
{
|
|
g_critical (G_STRLOC ": Unable to transform a value of type '%s' "
|
|
"into a value of type '%s'",
|
|
g_type_name (G_VALUE_TYPE (value)),
|
|
g_type_name (G_VALUE_TYPE (default_value)));
|
|
return;
|
|
}
|
|
|
|
/* will take ownership of the GValue */
|
|
g_property_set_default_value_internal (property, default_value);
|
|
}
|
|
|
|
/**
|
|
* g_property_get_default_value:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject
|
|
* @value: a #GValue
|
|
*
|
|
* Retrieves the default value of @property using the type of
|
|
* the @object instance, and places it into @value.
|
|
*
|
|
* The default value takes into account eventual overrides installed by the
|
|
* class of @gobject.
|
|
*
|
|
* This function will initialize @value to the type of the property,
|
|
* if @value is not initialized; otherwise, it will obey #GValue
|
|
* transformation rules between the type of the property and the type
|
|
* of the passed #GValue.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_get_default_value (GProperty *property,
|
|
gpointer gobject,
|
|
GValue *value)
|
|
{
|
|
const GValue *default_value;
|
|
GType gtype;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (G_IS_OBJECT (gobject));
|
|
|
|
gtype = G_OBJECT_TYPE (gobject);
|
|
default_value = g_property_get_default_value_internal (property, gtype);
|
|
|
|
/* initialize the GValue */
|
|
if (!G_IS_VALUE (value))
|
|
{
|
|
g_value_init (value, G_PARAM_SPEC (property)->value_type);
|
|
|
|
if (default_value != NULL)
|
|
g_value_copy (default_value, value);
|
|
}
|
|
else
|
|
{
|
|
if (default_value == NULL)
|
|
return;
|
|
|
|
if (!g_value_transform (default_value, value))
|
|
{
|
|
g_critical (G_STRLOC ": Unable to transform a value of type '%s' "
|
|
"into a value of type '%s'",
|
|
g_type_name (G_VALUE_TYPE (default_value)),
|
|
g_type_name (G_VALUE_TYPE (value)));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* g_property_override_default_value:
|
|
* @property: a #GProperty
|
|
* @class_type: the type that is overriding the default value of @property
|
|
* @value: a #GValue containing the new default value
|
|
*
|
|
* Overrides the default value of @property for the class of @class_type.
|
|
*
|
|
* This function should be called by sub-classes that desire overriding
|
|
* the default value of @property.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_override_default_value (GProperty *property,
|
|
GType class_type,
|
|
const GValue *value)
|
|
{
|
|
GValue *default_value;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (class_type != G_TYPE_INVALID);
|
|
g_return_if_fail (value != NULL);
|
|
|
|
default_value = g_new0 (GValue, 1);
|
|
g_value_init (default_value, G_PARAM_SPEC (property)->value_type);
|
|
|
|
if (!g_value_transform (value, default_value))
|
|
{
|
|
g_critical (G_STRLOC ": Unable to transform a value of type '%s' "
|
|
"into a value of type '%s'",
|
|
g_type_name (G_VALUE_TYPE (value)),
|
|
g_type_name (G_VALUE_TYPE (default_value)));
|
|
return;
|
|
}
|
|
|
|
/* will take ownership of the GValue */
|
|
g_property_override_default_value_internal (property, class_type, default_value);
|
|
}
|
|
|
|
/**
|
|
* g_property_set_default:
|
|
* @property: a #GProperty
|
|
* @...: the default value for the property
|
|
*
|
|
* Sets the default value of @property.
|
|
*
|
|
* This function is for the convenience of the C API users; language
|
|
* bindings should use the equivalent g_property_set_default_value()
|
|
* instead.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_set_default (GProperty *property,
|
|
...)
|
|
{
|
|
va_list var_args;
|
|
GValue *value;
|
|
char *error;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
|
|
va_start (var_args, property);
|
|
|
|
value = g_new0 (GValue, 1);
|
|
G_VALUE_COLLECT_INIT (value, G_PARAM_SPEC (property)->value_type, var_args, 0, &error);
|
|
if (error != NULL)
|
|
{
|
|
g_critical (G_STRLOC ": %s", error);
|
|
g_free (error);
|
|
g_value_unset (value);
|
|
g_free (value);
|
|
}
|
|
else
|
|
{
|
|
/* takes ownership of the GValue */
|
|
g_property_set_default_value_internal (property, value);
|
|
}
|
|
|
|
va_end (var_args);
|
|
}
|
|
|
|
/**
|
|
* g_property_get_default:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject
|
|
* @...: return location for the default value
|
|
*
|
|
* Retrieves the default value of @property for the given @gobject instance.
|
|
*
|
|
* The default value takes into account eventual overrides installed by the
|
|
* class of @gobject.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_get_default (GProperty *property,
|
|
gpointer gobject,
|
|
...)
|
|
{
|
|
const GValue *default_value;
|
|
GValue value = G_VALUE_INIT;
|
|
char *error = NULL;
|
|
va_list var_args;
|
|
GType gtype;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (G_IS_OBJECT (gobject));
|
|
|
|
g_value_init (&value, G_PARAM_SPEC (property)->value_type);
|
|
|
|
gtype = G_OBJECT_TYPE (gobject);
|
|
default_value = g_property_get_default_value_internal (property, gtype);
|
|
if (default_value != NULL)
|
|
g_value_copy (default_value, &value);
|
|
|
|
va_start (var_args, gobject);
|
|
|
|
G_VALUE_LCOPY (&value, var_args, 0, &error);
|
|
if (error != NULL)
|
|
{
|
|
g_warning (G_STRLOC ": %s", error);
|
|
g_free (error);
|
|
}
|
|
|
|
va_end (var_args);
|
|
g_value_unset (&value);
|
|
}
|
|
|
|
/**
|
|
* g_property_override_default:
|
|
* @property: a #GProperty
|
|
* @class_type: the type that is overriding the default value of @property
|
|
* @...: the default value for the property
|
|
*
|
|
* Overrides the default value of @property for the class of @class_type.
|
|
*
|
|
* This function should be called by sub-classes that desire overriding
|
|
* the default value of @property.
|
|
*
|
|
* This function is for the convenience of the C API users; language
|
|
* bindings should use the equivalent g_property_override_default_value()
|
|
* instead.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_override_default (GProperty *property,
|
|
GType class_type,
|
|
...)
|
|
{
|
|
va_list var_args;
|
|
GValue *value;
|
|
char *error;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (class_type != G_TYPE_INVALID);
|
|
|
|
va_start (var_args, class_type);
|
|
|
|
value = g_new0 (GValue, 1);
|
|
G_VALUE_COLLECT_INIT (value, G_PARAM_SPEC (property)->value_type, var_args, 0, &error);
|
|
if (error != NULL)
|
|
{
|
|
g_critical (G_STRLOC ": %s", error);
|
|
g_free (error);
|
|
g_value_unset (value);
|
|
g_free (value);
|
|
}
|
|
else
|
|
{
|
|
/* takes ownership of the GValue */
|
|
g_property_override_default_value_internal (property, class_type, value);
|
|
}
|
|
|
|
va_end (var_args);
|
|
}
|
|
|
|
/**
|
|
* g_property_set_va:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject instance
|
|
* @flags: collection flags, as a bitwise or of #GPropertyCollectFlags values
|
|
* @args: the value to set, inside a pointer to a #va_list
|
|
*
|
|
* Sets the value of @property for the given #GObject instance.
|
|
*
|
|
* This function is the va_list variant of g_property_set().
|
|
*
|
|
* Return value: %TRUE if the property was set to the new
|
|
* value, and %FALSE otherwise.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_set_va (GProperty *property,
|
|
gpointer gobject,
|
|
GPropertyCollectFlags flags,
|
|
va_list *args)
|
|
{
|
|
gboolean retval;
|
|
GType gtype;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
g_return_val_if_fail (property->is_installed, FALSE);
|
|
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
|
|
|
|
if ((property->flags & G_PROPERTY_WRITABLE) == 0)
|
|
{
|
|
g_critical ("The property '%s' of object '%s' is not writable",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
g_object_ref (gobject);
|
|
|
|
gtype = ((GParamSpec *) property)->value_type;
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
retval = g_boolean_property_set_value (property, gobject, va_arg (*args, gboolean));
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
retval = g_int8_property_set_value (property, gobject, va_arg (*args, gint));
|
|
break;
|
|
|
|
case 2:
|
|
retval = g_int16_property_set_value (property, gobject, va_arg (*args, gint));
|
|
break;
|
|
|
|
case 4:
|
|
retval = g_int32_property_set_value (property, gobject, va_arg (*args, gint));
|
|
break;
|
|
|
|
default:
|
|
retval = g_int_property_set_value (property, gobject, va_arg (*args, gint));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
retval = g_int64_property_set_value (property, gobject, va_arg (*args, gint64));
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
retval = g_long_property_set_value (property, gobject, va_arg (*args, glong));
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
retval = g_uint8_property_set_value (property, gobject, va_arg (*args, guint));
|
|
break;
|
|
|
|
case 2:
|
|
retval = g_uint16_property_set_value (property, gobject, va_arg (*args, guint));
|
|
break;
|
|
|
|
case 4:
|
|
retval = g_uint32_property_set_value (property, gobject, va_arg (*args, guint));
|
|
break;
|
|
|
|
default:
|
|
retval = g_uint_property_set_value (property, gobject, va_arg (*args, guint));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
retval = g_uint64_property_set_value (property, gobject, va_arg (*args, guint64));
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
retval = g_ulong_property_set_value (property, gobject, va_arg (*args, gulong));
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
retval = g_enum_property_set_value (property, gobject, va_arg (*args, gint));
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
retval = g_flags_property_set_value (property, gobject, va_arg (*args, guint));
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
retval = g_float_property_set_value (property, gobject, va_arg (*args, gdouble));
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
retval = g_double_property_set_value (property, gobject, va_arg (*args, gdouble));
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
retval = g_string_property_set_value (property, gobject, va_arg (*args, gchar *));
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
retval = g_boxed_property_set_value (property, gobject, va_arg (*args, gpointer));
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
retval = g_object_property_set_value (property, gobject, va_arg (*args, gpointer));
|
|
break;
|
|
|
|
case G_TYPE_POINTER:
|
|
retval = g_pointer_property_set_value (property, gobject, va_arg (*args, gpointer));
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (retval)
|
|
g_object_notify_by_pspec (gobject, (GParamSpec *) property);
|
|
|
|
g_object_unref (gobject);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* g_property_get_va:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject instance
|
|
* @flags: collection flags
|
|
* @args: a pointer to a #va_list with the property
|
|
*
|
|
* Retrieves the value of @property for the given #GObject instance.
|
|
*
|
|
* This function is the va_list variant of g_property_get().
|
|
*
|
|
* Return value: %TRUE if the value was successfully retrieved, and
|
|
* %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_get_va (GProperty *property,
|
|
gpointer gobject,
|
|
GPropertyCollectFlags flags,
|
|
va_list *args)
|
|
{
|
|
GType gtype;
|
|
gpointer ret_p = NULL;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
g_return_val_if_fail (property->is_installed, FALSE);
|
|
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
|
|
|
|
if ((property->flags & G_PROPERTY_READABLE) == 0)
|
|
{
|
|
g_critical ("The property '%s' of object '%s' is not readable",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
ret_p = va_arg (*args, gpointer);
|
|
if (ret_p == NULL)
|
|
{
|
|
g_critical (G_STRLOC ": value location for a property of type '%s' passed as NULL",
|
|
g_type_name (gtype));
|
|
return FALSE;
|
|
}
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
(* (gboolean *) ret_p) = g_boolean_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
(* (gint8 *) ret_p) = g_int8_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 2:
|
|
(* (gint16 *) ret_p) = g_int16_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 4:
|
|
(* (gint32 *) ret_p) = g_int32_property_get_value (property, gobject);
|
|
break;
|
|
|
|
default:
|
|
(* (gint *) ret_p) = g_int_property_get_value (property, gobject);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
(* (gint64 *) ret_p) = g_int64_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
(* (glong *) ret_p) = g_long_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
(* (guint8 *) ret_p) = g_uint8_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 2:
|
|
(* (guint16 *) ret_p) = g_uint16_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 4:
|
|
(* (guint32 *) ret_p) = g_uint32_property_get_value (property, gobject);
|
|
break;
|
|
|
|
default:
|
|
(* (guint *) ret_p) = g_uint_property_get_value (property, gobject);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
(* (guint64 *) ret_p) = g_uint64_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
(* (gulong *) ret_p) = g_ulong_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
(* (gint *) ret_p) = g_enum_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
(* (guint *) ret_p) = g_flags_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
(* (gfloat *) ret_p) = g_float_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
(* (gdouble *) ret_p) = g_double_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
{
|
|
const gchar *value;
|
|
|
|
value = g_string_property_get_value (property, gobject);
|
|
|
|
if (((flags & G_PROPERTY_COLLECT_COPY) != 0) &&
|
|
(property->flags & G_PROPERTY_COPY_GET) == 0)
|
|
{
|
|
(* (gchar **) ret_p) = g_strdup (value);
|
|
}
|
|
else
|
|
(* (gconstpointer *) ret_p) = value;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
{
|
|
gpointer boxed;
|
|
|
|
boxed = g_boxed_property_get_value (property, gobject);
|
|
|
|
if (((flags & G_PROPERTY_COLLECT_COPY) != 0) &&
|
|
(property->flags & G_PROPERTY_COPY_GET) == 0)
|
|
{
|
|
if (boxed != NULL)
|
|
(* (gpointer *) ret_p) = g_boxed_copy (gtype, boxed);
|
|
else
|
|
(* (gpointer *) ret_p) = NULL;
|
|
}
|
|
else
|
|
(* (gpointer *) ret_p) = (gpointer) boxed;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
{
|
|
gpointer obj = g_object_property_get_value (property, gobject);
|
|
|
|
if (((flags & G_PROPERTY_COLLECT_REF) != 0) &&
|
|
(property->flags & G_PROPERTY_COPY_GET) == 0)
|
|
{
|
|
if (obj != NULL)
|
|
(* (gpointer *) ret_p) = g_object_ref (obj);
|
|
else
|
|
(* (gpointer *) ret_p) = NULL;
|
|
}
|
|
else
|
|
(* (gpointer *) ret_p) = obj;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_POINTER:
|
|
(* (gpointer *) ret_p) = g_pointer_property_get_value (property, gobject);
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* g_property_set:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject instance
|
|
* @...: the value to be set
|
|
*
|
|
* Sets the value of the @property for the given #GObject instance.
|
|
*
|
|
* The value will either be copied or have its reference count increased.
|
|
*
|
|
* Returns: %TRUE if the property was set to the new value, and
|
|
* %FALSE otherwise.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_set (GProperty *property,
|
|
gpointer gobject,
|
|
...)
|
|
{
|
|
va_list args;
|
|
gboolean res;
|
|
|
|
va_start (args, gobject);
|
|
res = g_property_set_va (property, gobject, 0, &args);
|
|
va_end (args);
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* g_property_get:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject instance
|
|
* @...: a pointer to the value to be retrieved
|
|
*
|
|
* Retrieves the value of the @property for the given #GObject instance.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_get (GProperty *property,
|
|
gpointer gobject,
|
|
...)
|
|
{
|
|
va_list args;
|
|
gboolean retval;
|
|
|
|
va_start (args, gobject);
|
|
retval = g_property_get_va (property, gobject, 0, &args);
|
|
va_end (args);
|
|
|
|
return retval;
|
|
}
|
|
|
|
static inline gboolean
|
|
g_property_set_value_internal (GProperty *property,
|
|
gpointer gobject,
|
|
const GValue *value)
|
|
{
|
|
gboolean res = FALSE;
|
|
GType gtype;
|
|
|
|
if ((property->flags & G_PROPERTY_WRITABLE) == 0)
|
|
{
|
|
g_critical ("The property '%s' of object '%s' is not writable",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return FALSE;
|
|
}
|
|
|
|
g_object_ref (gobject);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
res = g_boolean_property_set_value (property, gobject, g_value_get_boolean (value));
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
gint val = g_value_get_int (value);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
res = g_int8_property_set_value (property, gobject, val);
|
|
break;
|
|
|
|
case 2:
|
|
res = g_int16_property_set_value (property, gobject, val);
|
|
break;
|
|
|
|
case 4:
|
|
res = g_int32_property_set_value (property, gobject, val);
|
|
break;
|
|
|
|
default:
|
|
res = g_int_property_set_value (property, gobject, val);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
res = g_int64_property_set_value (property, gobject, g_value_get_int64 (value));
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
res = g_long_property_set_value (property, gobject, g_value_get_long (value));
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
guint val = g_value_get_uint (value);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
res = g_uint8_property_set_value (property, gobject, val);
|
|
break;
|
|
|
|
case 2:
|
|
res = g_uint16_property_set_value (property, gobject, val);
|
|
break;
|
|
|
|
case 4:
|
|
res = g_uint32_property_set_value (property, gobject, val);
|
|
break;
|
|
|
|
default:
|
|
res = g_uint_property_set_value (property, gobject, val);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
res = g_uint64_property_set_value (property, gobject, g_value_get_uint64 (value));
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
res = g_ulong_property_set_value (property, gobject, g_value_get_ulong (value));
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
res = g_float_property_set_value (property, gobject, g_value_get_float (value));
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
res = g_double_property_set_value (property, gobject, g_value_get_double (value));
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
res = g_enum_property_set_value (property, gobject, g_value_get_enum (value));
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
res = g_flags_property_set_value (property, gobject, g_value_get_flags (value));
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
res = g_string_property_set_value (property, gobject, g_value_get_string (value));
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
res = g_boxed_property_set_value (property, gobject, g_value_get_boxed (value));
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
res = g_object_property_set_value (property, gobject, g_value_get_object (value));
|
|
break;
|
|
|
|
case G_TYPE_POINTER:
|
|
res = g_pointer_property_set_value (property, gobject, g_value_get_pointer (value));
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (G_VALUE_TYPE (value)));
|
|
break;
|
|
}
|
|
|
|
if (res)
|
|
g_object_notify_by_pspec (gobject, (GParamSpec *) property);
|
|
|
|
g_object_unref (gobject);
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* g_property_set_value:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject instance
|
|
* @value: a #GValue
|
|
*
|
|
* Sets the value of the @property for the given #GObject instance
|
|
* by unboxing it from the #GValue, honouring eventual transformation
|
|
* functions between the #GValue type and the property type.
|
|
*
|
|
* Returns: %TRUE if the new value was successfully set, and %FALSE
|
|
* otherwise.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_set_value (GProperty *property,
|
|
gpointer gobject,
|
|
const GValue *value)
|
|
{
|
|
GValue copy = { 0, };
|
|
GType gtype;
|
|
gboolean res;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
g_return_val_if_fail (property->is_installed, FALSE);
|
|
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
|
|
g_return_val_if_fail (value != NULL, FALSE);
|
|
|
|
/* do not go jump through the transformability hoops if we're getting
|
|
* the type we expect in the first place
|
|
*/
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
if (gtype == G_VALUE_TYPE (value))
|
|
return g_property_set_value_internal (property, gobject, value);
|
|
|
|
g_return_val_if_fail (g_value_type_transformable (G_VALUE_TYPE (value), gtype), FALSE);
|
|
|
|
g_value_init (©, gtype);
|
|
if (!g_value_transform (value, ©))
|
|
{
|
|
g_critical (G_STRLOC ": Unable to transform a value of type '%s' "
|
|
"into a value of type '%s'",
|
|
g_type_name (G_VALUE_TYPE (value)),
|
|
g_type_name (gtype));
|
|
g_value_unset (©);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
res = g_property_set_value_internal (property, gobject, ©);
|
|
|
|
g_value_unset (©);
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* g_property_get_value:
|
|
* @property: a #GProperty
|
|
* @gobject: a #GObject instance
|
|
* @value: a #GValue
|
|
*
|
|
* Retrieves the value of @property for the object instance, and
|
|
* boxes it inside a #GValue, honouring eventual transformation
|
|
* functions between the @value type and the property type.
|
|
*
|
|
* If @value is not initialized, this function will initialize it
|
|
* to the type of the @property before boxing the property value
|
|
* inside it.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
void
|
|
g_property_get_value (GProperty *property,
|
|
gpointer gobject,
|
|
GValue *value)
|
|
{
|
|
GType gtype;
|
|
GValue copy = { 0, };
|
|
GValue *value_p;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (property->is_installed);
|
|
g_return_if_fail (G_IS_OBJECT (gobject));
|
|
g_return_if_fail (value != NULL);
|
|
|
|
if ((property->flags & G_PROPERTY_READABLE) == 0)
|
|
{
|
|
g_critical ("The property '%s' of object '%s' is not readable",
|
|
G_PARAM_SPEC (property)->name,
|
|
G_OBJECT_TYPE_NAME (gobject));
|
|
return;
|
|
}
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
/* we allow passing an uninitialized GValue as a shortcut */
|
|
if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
|
|
{
|
|
g_value_init (value, gtype);
|
|
value_p = value;
|
|
}
|
|
else
|
|
{
|
|
g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (value), gtype));
|
|
|
|
g_value_init (©, gtype);
|
|
value_p = ©
|
|
}
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
g_value_set_boolean (value_p, g_boolean_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
gint val;
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
val = g_int8_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 2:
|
|
val = g_int16_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 4:
|
|
val = g_int32_property_get_value (property, gobject);
|
|
break;
|
|
|
|
default:
|
|
val = g_int_property_get_value (property, gobject);
|
|
break;
|
|
}
|
|
|
|
g_value_set_int (value_p, val);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
g_value_set_int64 (value_p, g_int64_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
g_value_set_long (value_p, g_long_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
guint val;
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
val = g_uint8_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 2:
|
|
val = g_uint16_property_get_value (property, gobject);
|
|
break;
|
|
|
|
case 4:
|
|
val = g_uint32_property_get_value (property, gobject);
|
|
break;
|
|
|
|
default:
|
|
val = g_uint_property_get_value (property, gobject);
|
|
break;
|
|
}
|
|
|
|
g_value_set_uint (value_p, val);
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
g_value_set_uint64 (value_p, g_uint64_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
g_value_set_ulong (value_p, g_ulong_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
g_value_set_string (value_p, g_string_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_CHAR:
|
|
g_value_set_schar (value_p, g_int8_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_UCHAR:
|
|
g_value_set_uchar (value_p, g_uint8_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
g_value_set_enum (value_p, g_enum_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
g_value_set_flags (value_p, g_flags_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
g_value_set_float (value_p, g_float_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
g_value_set_double (value_p, g_double_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
g_value_set_boxed (value_p, g_boxed_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
g_value_set_object (value_p, g_object_property_get_value (property, gobject));
|
|
break;
|
|
|
|
case G_TYPE_POINTER:
|
|
g_value_set_pointer (value_p, g_pointer_property_get_value (property, gobject));
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
break;
|
|
}
|
|
|
|
if (value_p == value)
|
|
return;
|
|
|
|
if (!g_value_transform (value_p, value))
|
|
{
|
|
g_critical (G_STRLOC ": Unable to transform a value of type '%s' into "
|
|
"a value of type '%s'",
|
|
g_type_name (gtype),
|
|
g_type_name (G_VALUE_TYPE (value)));
|
|
}
|
|
|
|
g_value_unset (value_p);
|
|
}
|
|
|
|
void
|
|
g_property_init_default (GProperty *property,
|
|
gpointer gobject)
|
|
{
|
|
const GValue *default_value;
|
|
|
|
g_return_if_fail (G_IS_PROPERTY (property));
|
|
g_return_if_fail (G_IS_OBJECT (gobject));
|
|
|
|
default_value = g_property_get_default_value_internal (property, G_OBJECT_TYPE (gobject));
|
|
if (default_value != NULL)
|
|
g_property_set_value_internal (property, gobject, default_value);
|
|
}
|
|
|
|
/**
|
|
* g_property_get_value_type:
|
|
* @property: a #GProperty
|
|
*
|
|
* Retrieves the #GType of the value stored by the property.
|
|
*
|
|
* If a prerequisite type has been set, it will be the returned type.
|
|
*
|
|
* Return value: a #GType
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
GType
|
|
g_property_get_value_type (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), G_TYPE_INVALID);
|
|
|
|
return G_PARAM_SPEC (property)->value_type;
|
|
}
|
|
|
|
/**
|
|
* g_property_validate:
|
|
* @property: a #GProperty
|
|
* @...: the value to validate
|
|
*
|
|
* Validates the passed value against the validation rules of
|
|
* the @property.
|
|
*
|
|
* Return value: %TRUE if the value is valid, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_validate (GProperty *property,
|
|
...)
|
|
{
|
|
gboolean retval = FALSE;
|
|
GType gtype;
|
|
va_list args;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
va_start (args, property);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
retval = g_boolean_property_validate (property, va_arg (args, gboolean));
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
retval = g_int8_property_validate (property, va_arg (args, gint));
|
|
break;
|
|
|
|
case 2:
|
|
retval = g_int16_property_validate (property, va_arg (args, gint));
|
|
break;
|
|
|
|
case 4:
|
|
retval = g_int32_property_validate (property, va_arg (args, gint));
|
|
break;
|
|
|
|
default:
|
|
retval = g_int_property_validate (property, va_arg (args, gint));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
retval = g_int64_property_validate (property, va_arg (args, gint64));
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
retval = g_long_property_validate (property, va_arg (args, glong));
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
retval = g_uint8_property_validate (property, va_arg (args, guint));
|
|
break;
|
|
|
|
case 2:
|
|
retval = g_uint16_property_validate (property, va_arg (args, guint));
|
|
break;
|
|
|
|
case 4:
|
|
retval = g_uint32_property_validate (property, va_arg (args, guint));
|
|
break;
|
|
|
|
default:
|
|
retval = g_uint_property_validate (property, va_arg (args, guint));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
retval = g_uint64_property_validate (property, va_arg (args, guint64));
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
retval = g_ulong_property_validate (property, va_arg (args, gulong));
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
retval = g_float_property_validate (property, va_arg (args, gdouble));
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
retval = g_double_property_validate (property, va_arg (args, gdouble));
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
retval = g_enum_property_validate (property, va_arg (args, gint));
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
retval = g_enum_property_validate (property, va_arg (args, guint));
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
retval = g_string_property_validate (property, va_arg (args, gchar *));
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
retval = g_boxed_property_validate (property, va_arg (args, gpointer));
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
retval = g_object_property_validate (property, va_arg (args, gpointer));
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
break;
|
|
}
|
|
|
|
va_end (args);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* g_property_validate_value:
|
|
* @property: a #GProperty
|
|
* @value: a #GValue initialized to the property type or to a type
|
|
* that is transformable into the property type
|
|
*
|
|
* Validates the value stored inside the passed #GValue against the
|
|
* @property rules.
|
|
*
|
|
* Return value: %TRUE if the value is valid, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_validate_value (GProperty *property,
|
|
GValue *value)
|
|
{
|
|
GValue copy = { 0, };
|
|
gboolean retval = FALSE;
|
|
GType gtype;
|
|
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
g_return_val_if_fail (value != NULL, FALSE);
|
|
|
|
gtype = G_PARAM_SPEC (property)->value_type;
|
|
|
|
g_return_val_if_fail (g_value_type_transformable (gtype, G_VALUE_TYPE (value)), FALSE);
|
|
|
|
g_value_init (©, gtype);
|
|
|
|
if (!g_value_transform (value, ©))
|
|
{
|
|
g_critical (G_STRLOC ": Unable to transform a value of type '%s' "
|
|
"to a value of type '%s'",
|
|
g_type_name (G_VALUE_TYPE (value)),
|
|
g_type_name (gtype));
|
|
g_value_unset (©);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (G_TYPE_FUNDAMENTAL (gtype))
|
|
{
|
|
case G_TYPE_BOOLEAN:
|
|
retval = g_boolean_property_validate (property, g_value_get_boolean (©));
|
|
break;
|
|
|
|
case G_TYPE_INT:
|
|
{
|
|
gint val = g_value_get_int (©);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
retval = g_int8_property_validate (property, val);
|
|
break;
|
|
|
|
case 2:
|
|
retval = g_int16_property_validate (property, val);
|
|
break;
|
|
|
|
case 4:
|
|
retval = g_int32_property_validate (property, val);
|
|
break;
|
|
|
|
default:
|
|
retval = g_int_property_validate (property, val);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_INT64:
|
|
retval = g_int64_property_validate (property, g_value_get_int64 (©));
|
|
break;
|
|
|
|
case G_TYPE_LONG:
|
|
retval = g_long_property_validate (property, g_value_get_long (©));
|
|
break;
|
|
|
|
case G_TYPE_UINT:
|
|
{
|
|
guint val = g_value_get_uint (©);
|
|
|
|
switch (property->type_size)
|
|
{
|
|
case 1:
|
|
retval = g_uint8_property_validate (property, val);
|
|
break;
|
|
|
|
case 2:
|
|
retval = g_uint16_property_validate (property, val);
|
|
break;
|
|
|
|
case 4:
|
|
retval = g_uint32_property_validate (property, val);
|
|
break;
|
|
|
|
default:
|
|
retval = g_uint_property_validate (property, val);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case G_TYPE_UINT64:
|
|
retval = g_uint64_property_validate (property, g_value_get_uint64 (©));
|
|
break;
|
|
|
|
case G_TYPE_ULONG:
|
|
retval = g_ulong_property_validate (property, g_value_get_ulong (©));
|
|
break;
|
|
|
|
case G_TYPE_FLOAT:
|
|
retval = g_float_property_validate (property, g_value_get_float (©));
|
|
break;
|
|
|
|
case G_TYPE_DOUBLE:
|
|
retval = g_double_property_validate (property, g_value_get_double (©));
|
|
break;
|
|
|
|
case G_TYPE_ENUM:
|
|
retval = g_enum_property_validate (property, g_value_get_enum (©));
|
|
break;
|
|
|
|
case G_TYPE_FLAGS:
|
|
retval = g_flags_property_validate (property, g_value_get_flags (©));
|
|
break;
|
|
|
|
case G_TYPE_STRING:
|
|
retval = g_string_property_validate (property, g_value_get_string (©));
|
|
break;
|
|
|
|
case G_TYPE_BOXED:
|
|
retval = g_boxed_property_validate (property, g_value_get_boxed (©));
|
|
break;
|
|
|
|
case G_TYPE_OBJECT:
|
|
retval = g_object_property_validate (property, g_value_get_object (©));
|
|
break;
|
|
|
|
default:
|
|
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
|
|
g_value_unset (©);
|
|
|
|
return retval;
|
|
}
|
|
|
|
/**
|
|
* g_property_is_writable:
|
|
* @property: a #GProperty
|
|
*
|
|
* Checks whether the @property has the %G_PROPERTY_WRITABLE flag set.
|
|
*
|
|
* Return value: %TRUE if the flag is set, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_is_writable (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
return (property->flags & G_PROPERTY_WRITABLE) != 0;
|
|
}
|
|
|
|
/**
|
|
* g_property_is_readable:
|
|
* @property: a #GProperty
|
|
*
|
|
* Checks whether the @property has the %G_PROPERTY_READABLE flag set.
|
|
*
|
|
* Return value: %TRUE if the flag is set, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_is_readable (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
return (property->flags & G_PROPERTY_READABLE) != 0 ||
|
|
(property->flags & G_PROPERTY_CONSTRUCT_ONLY) != 0;
|
|
}
|
|
|
|
/**
|
|
* g_property_is_deprecated:
|
|
* @property: a #GProperty
|
|
*
|
|
* Checks whether the @property has the %G_PROPERTY_DEPRECATED flag set.
|
|
*
|
|
* Return value: %TRUE if the flag is set, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_is_deprecated (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
return (property->flags & G_PROPERTY_DEPRECATED) != 0;
|
|
}
|
|
|
|
/**
|
|
* g_property_is_copy_set:
|
|
* @property: a #GProperty
|
|
*
|
|
* Checks whether the @property has the %G_PROPERTY_COPY_SET flag set.
|
|
*
|
|
* Return value: %TRUE if the flag is set, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_is_copy_set (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
return (property->flags & G_PROPERTY_COPY_SET) != 0;
|
|
}
|
|
|
|
/**
|
|
* g_property_is_copy_get:
|
|
* @property: a #GProperty
|
|
*
|
|
* Checks whether the @property has the %G_PROPERTY_COPY_GET flag set.
|
|
*
|
|
* Return value: %TRUE if the flag is set, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_is_copy_get (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
return (property->flags & G_PROPERTY_COPY_GET) != 0;
|
|
}
|
|
|
|
/**
|
|
* g_property_is_construct_only:
|
|
* @property: a #GProperty
|
|
*
|
|
* Checks whether the @property has the %G_PROPERTY_CONSTRUCT_ONLY flag
|
|
* set.
|
|
*
|
|
* Return value: %TRUE if the flag is set, and %FALSE otherwise
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
gboolean
|
|
g_property_is_construct_only (GProperty *property)
|
|
{
|
|
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
|
|
|
|
return (property->flags & G_PROPERTY_CONSTRUCT_ONLY) != 0;
|
|
}
|
|
|
|
static void
|
|
property_finalize (GParamSpec *pspec)
|
|
{
|
|
GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PROPERTY));
|
|
|
|
parent_class->finalize (pspec);
|
|
}
|
|
|
|
static gboolean
|
|
property_validate (GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
GProperty *property = G_PROPERTY (pspec);
|
|
|
|
if (!g_value_type_transformable (G_VALUE_TYPE (value), pspec->value_type))
|
|
return TRUE;
|
|
|
|
return !g_property_validate_value (property, value);
|
|
}
|
|
|
|
static gint
|
|
property_values_cmp (GParamSpec *pspec,
|
|
const GValue *value1,
|
|
const GValue *value2)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
property_value_set_default (GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
const GValue *v;
|
|
|
|
v = g_property_get_default_value_internal ((GProperty *) pspec, G_TYPE_INVALID);
|
|
|
|
if (v != NULL)
|
|
g_value_copy (v, value);
|
|
}
|
|
|
|
static void
|
|
property_class_init (GParamSpecClass *klass)
|
|
{
|
|
klass->value_type = G_TYPE_INVALID;
|
|
|
|
klass->value_validate = property_validate;
|
|
klass->values_cmp = property_values_cmp;
|
|
klass->value_set_default = property_value_set_default;
|
|
|
|
klass->finalize = property_finalize;
|
|
}
|
|
|
|
static void
|
|
property_init (GParamSpec *pspec)
|
|
{
|
|
GProperty *property = G_PROPERTY (pspec);
|
|
|
|
pspec->value_type = G_TYPE_INVALID;
|
|
|
|
property->field_offset = 0;
|
|
}
|
|
|
|
GType
|
|
g_property_get_type (void)
|
|
{
|
|
static volatile gsize pspec_type_id__volatile = 0;
|
|
|
|
if (g_once_init_enter (&pspec_type_id__volatile))
|
|
{
|
|
const GTypeInfo info = {
|
|
sizeof (GParamSpecClass),
|
|
NULL, NULL,
|
|
(GClassInitFunc) property_class_init,
|
|
NULL, NULL,
|
|
sizeof (GProperty),
|
|
0,
|
|
(GInstanceInitFunc) property_init,
|
|
};
|
|
|
|
GType pspec_type_id =
|
|
g_type_register_static (G_TYPE_PARAM,
|
|
g_intern_static_string ("GProperty"),
|
|
&info, 0);
|
|
|
|
g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
|
|
}
|
|
|
|
return pspec_type_id__volatile;
|
|
}
|