mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
gobject: Add GProperty
Dealing with GParamSpec is tedious and less efficient than necessary; property definitions should be able to either directly access a struct field or specify the accessors pair that control a property. On top of that, most of the property and accessor definition can be autogenerated from simple pre-processor directives. So, here's to you GProperty. GProperty is a GParamSpec sub-class that encapsulates all the types inside a single, opaque structure (to avoid leaking out implementation details); a GProperty can access the structure member holding the value of the property, or invoke the accessor functions passed to its constructor. Type safety is maintained through the GType system and without having to use GValue. Along with GProperty, this patch introduces a series of macros for automating the declaration and definition of property accessor functions, and for automating the collection and lcopy of values without going through GValue. GObject will recognize whether a GParamSpec used to set or get a property is really a GProperty, and thus will shortcircuit most of the GValue-based marshalled code, preferring the direct C function and direct argument collection instead of boxing/unboxing of GValues. https://bugzilla.gnome.org/show_bug.cgi?id=648526
This commit is contained in:
parent
51db2249d1
commit
72e08fb87b
@ -83,6 +83,7 @@
|
|||||||
<xi:include href="xml/signals.xml" />
|
<xi:include href="xml/signals.xml" />
|
||||||
<xi:include href="xml/gclosure.xml" />
|
<xi:include href="xml/gclosure.xml" />
|
||||||
<xi:include href="xml/value_arrays.xml" />
|
<xi:include href="xml/value_arrays.xml" />
|
||||||
|
<xi:include href="xml/gproperty.xml" />
|
||||||
<xi:include href="xml/gbinding.xml" />
|
<xi:include href="xml/gbinding.xml" />
|
||||||
</reference>
|
</reference>
|
||||||
<reference label="III">
|
<reference label="III">
|
||||||
|
@ -944,3 +944,84 @@ G_IS_BINDING
|
|||||||
g_binding_flags_get_type
|
g_binding_flags_get_type
|
||||||
g_binding_get_type
|
g_binding_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>gproperty</FILE>
|
||||||
|
GProperty
|
||||||
|
GPropertyFlags
|
||||||
|
GPropertyCollectFlags
|
||||||
|
<SUBSECTION>
|
||||||
|
g_property_is_writable
|
||||||
|
g_property_is_redable
|
||||||
|
g_property_is_deprecated
|
||||||
|
g_property_is_atomic
|
||||||
|
g_property_is_copy_set
|
||||||
|
g_property_is_copy_get
|
||||||
|
g_property_describe
|
||||||
|
g_property_set_range_values
|
||||||
|
g_property_get_range_values
|
||||||
|
g_property_set_range
|
||||||
|
g_property_get_range
|
||||||
|
g_property_set_default_value
|
||||||
|
g_property_set_default
|
||||||
|
g_property_override_default_value
|
||||||
|
g_property_override_default
|
||||||
|
g_property_get_default_value_for_type
|
||||||
|
g_property_get_default_value
|
||||||
|
g_property_get_default
|
||||||
|
g_property_set_prerequisite
|
||||||
|
g_property_validate_value
|
||||||
|
g_property_validate
|
||||||
|
g_property_set_value
|
||||||
|
g_property_set_va
|
||||||
|
g_property_set
|
||||||
|
g_property_get_value
|
||||||
|
g_property_get_va
|
||||||
|
g_property_get
|
||||||
|
GPropertyLockFunc
|
||||||
|
GPropertyUnlockFunc
|
||||||
|
g_property_set_lock_functions
|
||||||
|
g_property_lock
|
||||||
|
g_property_unlock
|
||||||
|
g_property_canonicalize_name
|
||||||
|
<SUBSECTION>
|
||||||
|
g_boolean_property_new
|
||||||
|
g_int_property_new
|
||||||
|
g_int8_property_new
|
||||||
|
g_int16_property_new
|
||||||
|
g_int32_property_new
|
||||||
|
g_int64_property_new
|
||||||
|
g_long_property_new
|
||||||
|
g_char_property_new
|
||||||
|
g_uint_property_new
|
||||||
|
g_uint8_property_new
|
||||||
|
g_uint16_property_new
|
||||||
|
g_uint32_property_new
|
||||||
|
g_uint64_property_new
|
||||||
|
g_ulong_property_new
|
||||||
|
g_uchar_property_new
|
||||||
|
g_unichar_property_new
|
||||||
|
g_float_property_new
|
||||||
|
g_double_property_new
|
||||||
|
g_enum_property_new
|
||||||
|
g_flags_property_new
|
||||||
|
g_string_property_new
|
||||||
|
g_boxed_property_new
|
||||||
|
g_object_property_new
|
||||||
|
g_pointer_property_new
|
||||||
|
<SUBSECTION>
|
||||||
|
G_DECLARE_PROPERTY_GET
|
||||||
|
G_DECLARE_PROPERTY_SET
|
||||||
|
G_DECLARE_PROPERTY_GET_SET
|
||||||
|
G_DEFINE_PROPERTY_GET_WITH_CODE
|
||||||
|
G_DEFINE_PROPERTY_GET
|
||||||
|
G_DEFINE_PROPERTY_SET_WITH_CODE
|
||||||
|
G_DEFINE_PROPERTY_SET
|
||||||
|
G_DEFINE_PROPERTY_GET_SET
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
G_PROPERTY
|
||||||
|
G_IS_PROPERTY
|
||||||
|
G_TYPE_PROPERTY
|
||||||
|
<SUBSECTION Private>
|
||||||
|
g_property_get_type
|
||||||
|
</SECTION>
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <gobject/gobject.h>
|
#include <gobject/gobject.h>
|
||||||
#include <gobject/gparam.h>
|
#include <gobject/gparam.h>
|
||||||
#include <gobject/gparamspecs.h>
|
#include <gobject/gparamspecs.h>
|
||||||
|
#include <gobject/gproperty.h>
|
||||||
#include <gobject/gsignal.h>
|
#include <gobject/gsignal.h>
|
||||||
#include <gobject/gsourceclosure.h>
|
#include <gobject/gsourceclosure.h>
|
||||||
#include <gobject/gtype.h>
|
#include <gobject/gtype.h>
|
||||||
|
@ -97,6 +97,7 @@ gobject_public_h_sources = \
|
|||||||
gobject.h \
|
gobject.h \
|
||||||
gparam.h \
|
gparam.h \
|
||||||
gparamspecs.h \
|
gparamspecs.h \
|
||||||
|
gproperty.h \
|
||||||
gsignal.h \
|
gsignal.h \
|
||||||
gsourceclosure.h \
|
gsourceclosure.h \
|
||||||
gtype.h \
|
gtype.h \
|
||||||
@ -126,6 +127,7 @@ gobject_c_sources = \
|
|||||||
gobject_trace.h \
|
gobject_trace.h \
|
||||||
gparam.c \
|
gparam.c \
|
||||||
gparamspecs.c \
|
gparamspecs.c \
|
||||||
|
gproperty.c \
|
||||||
gsignal.c \
|
gsignal.c \
|
||||||
gsourceclosure.c \
|
gsourceclosure.c \
|
||||||
gtype.c \
|
gtype.c \
|
||||||
|
@ -545,9 +545,9 @@ g_object_class_install_property (GObjectClass *class,
|
|||||||
class->flags |= CLASS_HAS_PROPS_FLAG;
|
class->flags |= CLASS_HAS_PROPS_FLAG;
|
||||||
|
|
||||||
g_return_if_fail (pspec->flags & (G_PARAM_READABLE | G_PARAM_WRITABLE));
|
g_return_if_fail (pspec->flags & (G_PARAM_READABLE | G_PARAM_WRITABLE));
|
||||||
if (pspec->flags & G_PARAM_WRITABLE)
|
if (pspec->flags & G_PARAM_WRITABLE && !G_IS_PROPERTY (pspec))
|
||||||
g_return_if_fail (class->set_property != NULL);
|
g_return_if_fail (class->set_property != NULL);
|
||||||
if (pspec->flags & G_PARAM_READABLE)
|
if (pspec->flags & G_PARAM_READABLE && !G_IS_PROPERTY (pspec))
|
||||||
g_return_if_fail (class->get_property != NULL);
|
g_return_if_fail (class->get_property != NULL);
|
||||||
g_return_if_fail (property_id > 0);
|
g_return_if_fail (property_id > 0);
|
||||||
g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
|
g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
|
||||||
@ -558,6 +558,9 @@ g_object_class_install_property (GObjectClass *class,
|
|||||||
|
|
||||||
install_property_internal (G_OBJECT_CLASS_TYPE (class), property_id, pspec);
|
install_property_internal (G_OBJECT_CLASS_TYPE (class), property_id, pspec);
|
||||||
|
|
||||||
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
_g_property_set_installed (G_PROPERTY (pspec), class, G_OBJECT_CLASS_TYPE (class));
|
||||||
|
|
||||||
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
|
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
|
||||||
class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
|
class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
|
||||||
|
|
||||||
@ -662,9 +665,9 @@ g_object_class_install_properties (GObjectClass *oclass,
|
|||||||
|
|
||||||
g_return_if_fail (pspec != NULL);
|
g_return_if_fail (pspec != NULL);
|
||||||
|
|
||||||
if (pspec->flags & G_PARAM_WRITABLE)
|
if (!G_IS_PROPERTY (pspec) && pspec->flags & G_PARAM_WRITABLE)
|
||||||
g_return_if_fail (oclass->set_property != NULL);
|
g_return_if_fail (oclass->set_property != NULL);
|
||||||
if (pspec->flags & G_PARAM_READABLE)
|
if (!G_IS_PROPERTY (pspec) && pspec->flags & G_PARAM_READABLE)
|
||||||
g_return_if_fail (oclass->get_property != NULL);
|
g_return_if_fail (oclass->get_property != NULL);
|
||||||
g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
|
g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
|
||||||
if (pspec->flags & G_PARAM_CONSTRUCT)
|
if (pspec->flags & G_PARAM_CONSTRUCT)
|
||||||
@ -675,6 +678,9 @@ g_object_class_install_properties (GObjectClass *oclass,
|
|||||||
oclass->flags |= CLASS_HAS_PROPS_FLAG;
|
oclass->flags |= CLASS_HAS_PROPS_FLAG;
|
||||||
install_property_internal (oclass_type, i, pspec);
|
install_property_internal (oclass_type, i, pspec);
|
||||||
|
|
||||||
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
_g_property_set_installed (G_PROPERTY (pspec), oclass, oclass_type);
|
||||||
|
|
||||||
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
|
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
|
||||||
oclass->construct_properties = g_slist_prepend (oclass->construct_properties, pspec);
|
oclass->construct_properties = g_slist_prepend (oclass->construct_properties, pspec);
|
||||||
|
|
||||||
@ -906,6 +912,129 @@ g_object_class_list_properties (GObjectClass *class,
|
|||||||
return pspecs;
|
return pspecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
override_property_default_value (GObjectClass *oclass,
|
||||||
|
GProperty *property,
|
||||||
|
const GValue *value)
|
||||||
|
{
|
||||||
|
g_property_override_default_value (property, G_OBJECT_CLASS_TYPE (oclass), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_object_class_override_property_default_value:
|
||||||
|
* @oclass: a #GObjectClass
|
||||||
|
* @property_name: the name of the property to override
|
||||||
|
* @value: a valid #GValue containing the new default value
|
||||||
|
*
|
||||||
|
* Overrides the default value of @property_name for @oclass with
|
||||||
|
* a new value.
|
||||||
|
*
|
||||||
|
* See g_object_class_override_property_default() for more information.
|
||||||
|
*
|
||||||
|
* This function is meant for language bindings.
|
||||||
|
*
|
||||||
|
* Since: 2.36
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_object_class_override_property_default_value (GObjectClass *oclass,
|
||||||
|
const gchar *property_name,
|
||||||
|
const GValue *default_value)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
pspec = g_object_class_find_property (oclass, property_name);
|
||||||
|
if (pspec == NULL)
|
||||||
|
{
|
||||||
|
g_critical ("The class '%s' does not have a property named '%s'",
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (oclass)),
|
||||||
|
property_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!G_IS_PROPERTY (pspec))
|
||||||
|
{
|
||||||
|
g_critical ("The property '%s' of class '%s' is of type '%s' and "
|
||||||
|
"not a GProperty. Overriding the default is allowed "
|
||||||
|
"only on properties defined using the GProperty API.",
|
||||||
|
G_PARAM_SPEC (pspec)->name,
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (oclass)),
|
||||||
|
g_type_name (G_PARAM_SPEC_TYPE (pspec)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
override_property_default_value (oclass, G_PROPERTY (pspec), default_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_object_class_override_property_default:
|
||||||
|
* @oclass: a #GObjectClass
|
||||||
|
* @property_name: the name of the property to override
|
||||||
|
* @...: the new default value of the property
|
||||||
|
*
|
||||||
|
* Sets the default value of @property_name for the given #GObject
|
||||||
|
* class.
|
||||||
|
*
|
||||||
|
* This function can only be used with properties installed using
|
||||||
|
* the #GProperty API.
|
||||||
|
*
|
||||||
|
* This function is the equivalent of:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* GParamSpec *pspec = g_object_class_find_property (oclass, property_name);
|
||||||
|
*
|
||||||
|
* g_property_set_default (G_PROPERTY (pspec), oclass, new_value);
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Since: 2.36
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_object_class_override_property_default (GObjectClass *oclass,
|
||||||
|
const gchar *property_name,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
GValue value = { 0, };
|
||||||
|
va_list args;
|
||||||
|
gchar *error = NULL;
|
||||||
|
|
||||||
|
pspec = g_object_class_find_property (oclass, property_name);
|
||||||
|
if (pspec == NULL)
|
||||||
|
{
|
||||||
|
g_critical ("The class '%s' does not have a property named '%s'",
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (oclass)),
|
||||||
|
property_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!G_IS_PROPERTY (pspec))
|
||||||
|
{
|
||||||
|
g_critical ("The property '%s' of class '%s' is of type '%s' and "
|
||||||
|
"not a GProperty. Overriding the default is allowed "
|
||||||
|
"only on properties defined using the GProperty API.",
|
||||||
|
G_PARAM_SPEC (pspec)->name,
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (oclass)),
|
||||||
|
g_type_name (G_PARAM_SPEC_TYPE (pspec)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start (args, property_name);
|
||||||
|
|
||||||
|
G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec), args, 0, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_critical (G_STRLOC ": %s", error);
|
||||||
|
g_free (error);
|
||||||
|
va_end (args);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
override_property_default_value (oclass, G_PROPERTY (pspec), &value);
|
||||||
|
|
||||||
|
g_value_unset (&value);
|
||||||
|
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_object_interface_list_properties:
|
* g_object_interface_list_properties:
|
||||||
* @g_iface: any interface vtable for the interface, or the default
|
* @g_iface: any interface vtable for the interface, or the default
|
||||||
@ -1290,8 +1419,15 @@ object_get_property (GObject *object,
|
|||||||
redirect = g_param_spec_get_redirect_target (pspec);
|
redirect = g_param_spec_get_redirect_target (pspec);
|
||||||
if (redirect)
|
if (redirect)
|
||||||
pspec = redirect;
|
pspec = redirect;
|
||||||
|
|
||||||
class->get_property (object, param_id, value, pspec);
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
{
|
||||||
|
GProperty *prop = G_PROPERTY (pspec);
|
||||||
|
|
||||||
|
g_property_get_value (prop, object, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
class->get_property (object, param_id, value, pspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -1352,14 +1488,21 @@ object_set_property (GObject *object,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GParamSpec *notify_pspec;
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
{
|
||||||
|
g_property_set_value ((GProperty *) pspec, object, &tmp_value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GParamSpec *notify_pspec;
|
||||||
|
|
||||||
class->set_property (object, param_id, &tmp_value, pspec);
|
class->set_property (object, param_id, &tmp_value, pspec);
|
||||||
|
|
||||||
notify_pspec = get_notify_pspec (pspec);
|
notify_pspec = get_notify_pspec (pspec);
|
||||||
|
|
||||||
if (notify_pspec != NULL)
|
if (notify_pspec != NULL)
|
||||||
g_object_notify_queue_add (object, nqueue, notify_pspec);
|
g_object_notify_queue_add (object, nqueue, notify_pspec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_value_unset (&tmp_value);
|
g_value_unset (&tmp_value);
|
||||||
}
|
}
|
||||||
@ -1883,35 +2026,22 @@ g_object_constructed (GObject *object)
|
|||||||
/* empty default impl to allow unconditional upchaining */
|
/* empty default impl to allow unconditional upchaining */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static inline void
|
||||||
* g_object_set_valist: (skip)
|
object_set_valist_internal (GObject *object,
|
||||||
* @object: a #GObject
|
const gchar *first_property_name,
|
||||||
* @first_property_name: name of the first property to set
|
va_list *args)
|
||||||
* @var_args: value for the first property, followed optionally by more
|
|
||||||
* name/value pairs, followed by %NULL
|
|
||||||
*
|
|
||||||
* Sets properties on an object.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
g_object_set_valist (GObject *object,
|
|
||||||
const gchar *first_property_name,
|
|
||||||
va_list var_args)
|
|
||||||
{
|
{
|
||||||
GObjectNotifyQueue *nqueue;
|
GObjectNotifyQueue *nqueue;
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
|
|
||||||
g_return_if_fail (G_IS_OBJECT (object));
|
|
||||||
|
|
||||||
g_object_ref (object);
|
g_object_ref (object);
|
||||||
nqueue = g_object_notify_queue_freeze (object, FALSE);
|
nqueue = g_object_notify_queue_freeze (object, FALSE);
|
||||||
|
|
||||||
name = first_property_name;
|
name = first_property_name;
|
||||||
while (name)
|
while (name)
|
||||||
{
|
{
|
||||||
GValue value = G_VALUE_INIT;
|
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
gchar *error = NULL;
|
|
||||||
|
|
||||||
pspec = g_param_spec_pool_lookup (pspec_pool,
|
pspec = g_param_spec_pool_lookup (pspec_pool,
|
||||||
name,
|
name,
|
||||||
G_OBJECT_TYPE (object),
|
G_OBJECT_TYPE (object),
|
||||||
@ -1939,26 +2069,136 @@ g_object_set_valist (GObject *object,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args,
|
if (G_IS_PROPERTY (pspec))
|
||||||
0, &error);
|
{
|
||||||
if (error)
|
GProperty *property = (GProperty *) pspec;
|
||||||
{
|
|
||||||
g_warning ("%s: %s", G_STRFUNC, error);
|
g_property_set_va (property, object, 0, args);
|
||||||
g_free (error);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GValue value = G_VALUE_INIT;
|
||||||
|
gchar *error = NULL;
|
||||||
|
|
||||||
|
G_VALUE_COLLECT_INIT (&value, pspec->value_type, *args, 0, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_warning ("%s: %s", G_STRFUNC, error);
|
||||||
|
g_free (error);
|
||||||
|
g_value_unset (&value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_set_property (object, pspec, &value, nqueue);
|
||||||
g_value_unset (&value);
|
g_value_unset (&value);
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
name = va_arg (*args, gchar*);
|
||||||
object_set_property (object, pspec, &value, nqueue);
|
|
||||||
g_value_unset (&value);
|
|
||||||
|
|
||||||
name = va_arg (var_args, gchar*);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_notify_queue_thaw (object, nqueue);
|
g_object_notify_queue_thaw (object, nqueue);
|
||||||
g_object_unref (object);
|
g_object_unref (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_object_set_valist: (skip)
|
||||||
|
* @object: a #GObject
|
||||||
|
* @first_property_name: name of the first property to set
|
||||||
|
* @var_args: value for the first property, followed optionally by more
|
||||||
|
* name/value pairs, followed by %NULL
|
||||||
|
*
|
||||||
|
* Sets properties on an object.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_object_set_valist (GObject *object,
|
||||||
|
const gchar *first_property_name,
|
||||||
|
va_list var_args)
|
||||||
|
{
|
||||||
|
va_list va_copy;
|
||||||
|
|
||||||
|
g_return_if_fail (G_IS_OBJECT (object));
|
||||||
|
|
||||||
|
G_VA_COPY (va_copy, var_args);
|
||||||
|
object_set_valist_internal (object, first_property_name, &va_copy);
|
||||||
|
va_end (va_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
object_get_valist_internal (GObject *object,
|
||||||
|
const gchar *first_property_name,
|
||||||
|
va_list *args)
|
||||||
|
{
|
||||||
|
const gchar *name;
|
||||||
|
|
||||||
|
g_object_ref (object);
|
||||||
|
|
||||||
|
name = first_property_name;
|
||||||
|
|
||||||
|
while (name)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
pspec = g_param_spec_pool_lookup (pspec_pool,
|
||||||
|
name,
|
||||||
|
G_OBJECT_TYPE (object),
|
||||||
|
TRUE);
|
||||||
|
if (!pspec)
|
||||||
|
{
|
||||||
|
g_warning ("%s: object class `%s' has no property named `%s'",
|
||||||
|
G_STRFUNC,
|
||||||
|
G_OBJECT_TYPE_NAME (object),
|
||||||
|
name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(pspec->flags & G_PARAM_READABLE))
|
||||||
|
{
|
||||||
|
g_warning ("%s: property `%s' of object class `%s' is not readable",
|
||||||
|
G_STRFUNC,
|
||||||
|
pspec->name,
|
||||||
|
G_OBJECT_TYPE_NAME (object));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
{
|
||||||
|
GProperty *property = (GProperty *) pspec;
|
||||||
|
GPropertyFlags flags = G_PROPERTY_COLLECT_REF
|
||||||
|
| G_PROPERTY_COLLECT_COPY;
|
||||||
|
|
||||||
|
/* we use G_PROPERTY_COLLECT_COPY and G_PROPERTY_COLLECT_REF to
|
||||||
|
* preserve the semantics of GValues holding a typed pointer
|
||||||
|
* value, like GObject, GBoxed and strings
|
||||||
|
*/
|
||||||
|
if (!g_property_get_va (property, object, flags, args))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GValue value = G_VALUE_INIT;
|
||||||
|
gchar *error;
|
||||||
|
|
||||||
|
g_value_init (&value, pspec->value_type);
|
||||||
|
|
||||||
|
object_get_property (object, pspec, &value);
|
||||||
|
|
||||||
|
G_VALUE_LCOPY (&value, *args, 0, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
{
|
||||||
|
g_warning ("%s: %s", G_STRFUNC, error);
|
||||||
|
g_free (error);
|
||||||
|
g_value_unset (&value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_value_unset (&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
name = va_arg (*args, gchar*);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (object);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_object_get_valist: (skip)
|
* g_object_get_valist: (skip)
|
||||||
* @object: a #GObject
|
* @object: a #GObject
|
||||||
@ -1979,60 +2219,13 @@ g_object_get_valist (GObject *object,
|
|||||||
const gchar *first_property_name,
|
const gchar *first_property_name,
|
||||||
va_list var_args)
|
va_list var_args)
|
||||||
{
|
{
|
||||||
const gchar *name;
|
va_list va_copy;
|
||||||
|
|
||||||
g_return_if_fail (G_IS_OBJECT (object));
|
g_return_if_fail (G_IS_OBJECT (object));
|
||||||
|
|
||||||
g_object_ref (object);
|
G_VA_COPY (va_copy, var_args);
|
||||||
|
object_get_valist_internal (object, first_property_name, &va_copy);
|
||||||
name = first_property_name;
|
va_end (va_copy);
|
||||||
|
|
||||||
while (name)
|
|
||||||
{
|
|
||||||
GValue value = G_VALUE_INIT;
|
|
||||||
GParamSpec *pspec;
|
|
||||||
gchar *error;
|
|
||||||
|
|
||||||
pspec = g_param_spec_pool_lookup (pspec_pool,
|
|
||||||
name,
|
|
||||||
G_OBJECT_TYPE (object),
|
|
||||||
TRUE);
|
|
||||||
if (!pspec)
|
|
||||||
{
|
|
||||||
g_warning ("%s: object class `%s' has no property named `%s'",
|
|
||||||
G_STRFUNC,
|
|
||||||
G_OBJECT_TYPE_NAME (object),
|
|
||||||
name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!(pspec->flags & G_PARAM_READABLE))
|
|
||||||
{
|
|
||||||
g_warning ("%s: property `%s' of object class `%s' is not readable",
|
|
||||||
G_STRFUNC,
|
|
||||||
pspec->name,
|
|
||||||
G_OBJECT_TYPE_NAME (object));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_value_init (&value, pspec->value_type);
|
|
||||||
|
|
||||||
object_get_property (object, pspec, &value);
|
|
||||||
|
|
||||||
G_VALUE_LCOPY (&value, var_args, 0, &error);
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
g_warning ("%s: %s", G_STRFUNC, error);
|
|
||||||
g_free (error);
|
|
||||||
g_value_unset (&value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_value_unset (&value);
|
|
||||||
|
|
||||||
name = va_arg (var_args, gchar*);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2055,7 +2248,7 @@ g_object_set (gpointer _object,
|
|||||||
g_return_if_fail (G_IS_OBJECT (object));
|
g_return_if_fail (G_IS_OBJECT (object));
|
||||||
|
|
||||||
va_start (var_args, first_property_name);
|
va_start (var_args, first_property_name);
|
||||||
g_object_set_valist (object, first_property_name, var_args);
|
object_set_valist_internal (object, first_property_name, &var_args);
|
||||||
va_end (var_args);
|
va_end (var_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2106,7 +2299,7 @@ g_object_get (gpointer _object,
|
|||||||
g_return_if_fail (G_IS_OBJECT (object));
|
g_return_if_fail (G_IS_OBJECT (object));
|
||||||
|
|
||||||
va_start (var_args, first_property_name);
|
va_start (var_args, first_property_name);
|
||||||
g_object_get_valist (object, first_property_name, var_args);
|
object_get_valist_internal (object, first_property_name, &var_args);
|
||||||
va_end (var_args);
|
va_end (var_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,6 +402,15 @@ GParamSpec* g_object_interface_find_property (gpointer g_iface,
|
|||||||
GParamSpec**g_object_interface_list_properties (gpointer g_iface,
|
GParamSpec**g_object_interface_list_properties (gpointer g_iface,
|
||||||
guint *n_properties_p);
|
guint *n_properties_p);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_object_class_override_property_default (GObjectClass *oclass,
|
||||||
|
const gchar *property_name,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_object_class_override_property_default_value (GObjectClass *oclass,
|
||||||
|
const gchar *property_name,
|
||||||
|
const GValue *default_value);
|
||||||
|
|
||||||
GType g_object_get_type (void) G_GNUC_CONST;
|
GType g_object_get_type (void) G_GNUC_CONST;
|
||||||
gpointer g_object_new (GType object_type,
|
gpointer g_object_new (GType object_type,
|
||||||
const gchar *first_property_name,
|
const gchar *first_property_name,
|
||||||
|
@ -222,8 +222,8 @@ g_param_spec_steal_qdata
|
|||||||
g_param_spec_set_qdata
|
g_param_spec_set_qdata
|
||||||
g_param_spec_set_qdata_full
|
g_param_spec_set_qdata_full
|
||||||
g_param_spec_get_qdata
|
g_param_spec_get_qdata
|
||||||
g_param_spec_set_static_nick
|
|
||||||
g_param_spec_set_static_blurb
|
g_param_spec_set_static_blurb
|
||||||
|
g_param_spec_set_static_nick
|
||||||
g_param_value_convert
|
g_param_value_convert
|
||||||
g_param_value_defaults
|
g_param_value_defaults
|
||||||
g_param_values_cmp
|
g_param_values_cmp
|
||||||
@ -240,6 +240,58 @@ g_value_set_param
|
|||||||
g_value_dup_param
|
g_value_dup_param
|
||||||
g_value_take_param
|
g_value_take_param
|
||||||
g_value_set_param_take_ownership
|
g_value_set_param_take_ownership
|
||||||
|
g_boolean_property_new
|
||||||
|
g_boxed_property_new
|
||||||
|
g_double_property_new
|
||||||
|
g_flags_property_new
|
||||||
|
g_float_property_new
|
||||||
|
g_enum_property_new
|
||||||
|
g_int16_property_new
|
||||||
|
g_int32_property_new
|
||||||
|
g_int64_property_new
|
||||||
|
g_int8_property_new
|
||||||
|
g_int_property_new
|
||||||
|
g_long_property_new
|
||||||
|
g_object_property_new
|
||||||
|
g_pointer_property_new
|
||||||
|
g_property_canonicalize_name
|
||||||
|
g_property_describe
|
||||||
|
g_property_get
|
||||||
|
g_property_get_default
|
||||||
|
g_property_get_default_value
|
||||||
|
g_property_get_default_value_for_type
|
||||||
|
g_property_get_range
|
||||||
|
g_property_get_range_values
|
||||||
|
g_property_get_type
|
||||||
|
g_property_get_va
|
||||||
|
g_property_get_value
|
||||||
|
g_property_get_value_type
|
||||||
|
g_property_is_atomic
|
||||||
|
g_property_is_copy_get
|
||||||
|
g_property_is_copy_set
|
||||||
|
g_property_is_deprecated
|
||||||
|
g_property_is_readable
|
||||||
|
g_property_is_writable
|
||||||
|
g_property_lock
|
||||||
|
g_property_set
|
||||||
|
g_property_set_default
|
||||||
|
g_property_set_default_value
|
||||||
|
g_property_set_lock_functions
|
||||||
|
g_property_set_prerequisite
|
||||||
|
g_property_set_range
|
||||||
|
g_property_set_range_values
|
||||||
|
g_property_set_va
|
||||||
|
g_property_set_value
|
||||||
|
g_property_unlock
|
||||||
|
g_property_validate
|
||||||
|
g_property_validate_value
|
||||||
|
g_string_property_new
|
||||||
|
g_uint16_property_new
|
||||||
|
g_uint32_property_new
|
||||||
|
g_uint64_property_new
|
||||||
|
g_uint8_property_new
|
||||||
|
g_uint_property_new
|
||||||
|
g_ulong_property_new
|
||||||
g_pointer_type_register_static
|
g_pointer_type_register_static
|
||||||
g_strdup_value_contents
|
g_strdup_value_contents
|
||||||
g_value_set_boolean
|
g_value_set_boolean
|
||||||
|
5604
gobject/gproperty.c
Normal file
5604
gobject/gproperty.c
Normal file
File diff suppressed because it is too large
Load Diff
745
gobject/gproperty.h
Normal file
745
gobject/gproperty.h
Normal file
@ -0,0 +1,745 @@
|
|||||||
|
/* gproperty.h: Property definitions for GObject
|
||||||
|
*
|
||||||
|
* Copyright © 2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined (__GLIB_GOBJECT_H_INSIDE__) && !defined (GOBJECT_COMPILATION)
|
||||||
|
#error "Only <glib-object.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __G_PROPERTY_H__
|
||||||
|
#define __G_PROPERTY_H__
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gobject/gparam.h>
|
||||||
|
#include <gobject/gobject.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define G_TYPE_PROPERTY (g_property_get_type ())
|
||||||
|
#define G_PROPERTY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_PROPERTY, GProperty))
|
||||||
|
#define G_IS_PROPERTY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_PROPERTY))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GProperty:
|
||||||
|
*
|
||||||
|
* The <structname>GProperty</structname> structure is an opaque structure
|
||||||
|
* whose members cannot be directly accessed.
|
||||||
|
*
|
||||||
|
* Since: 2.36
|
||||||
|
*/
|
||||||
|
typedef struct _GProperty GProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GPropertyFlags:
|
||||||
|
* @G_PROPERTY_READABLE: Whether the property is readable
|
||||||
|
* @G_PROPERTY_WRITABLE: Whether the property is writable
|
||||||
|
* @G_PROPERTY_READWRITE: Whether the property is readable and writable
|
||||||
|
* @G_PROPERTY_DEPRECATED: Whether the property is deprecated and should
|
||||||
|
* not be accessed in newly written code.
|
||||||
|
* @G_PROPERTY_ATOMIC: Whether the autogenerated setter function should
|
||||||
|
* be thread-safe, and acquire a lock when changing the value of the
|
||||||
|
* property.
|
||||||
|
* @G_PROPERTY_COPY_SET: Whether the property will make a copy or
|
||||||
|
* take a reference when being set to a new value
|
||||||
|
* @G_PROPERTY_COPY_GET: Whether the property will make a copy or
|
||||||
|
* take a reference when the value is being retrieved
|
||||||
|
* @G_PROPERTY_COPY: Whether the property will make a copy, or take a
|
||||||
|
* reference, of the new value being set, and return a copy, or
|
||||||
|
* increase the reference count, of the value being retrieved
|
||||||
|
*
|
||||||
|
* Flags for properties declared using #GProperty and relative macros.
|
||||||
|
*
|
||||||
|
* This enumeration might be extended at later date.
|
||||||
|
*
|
||||||
|
* Since: 2.36
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
G_PROPERTY_READABLE = 1 << 0,
|
||||||
|
G_PROPERTY_WRITABLE = 1 << 1,
|
||||||
|
G_PROPERTY_READWRITE = (G_PROPERTY_READABLE | G_PROPERTY_WRITABLE),
|
||||||
|
|
||||||
|
G_PROPERTY_DEPRECATED = 1 << 2,
|
||||||
|
G_PROPERTY_ATOMIC = 1 << 3,
|
||||||
|
G_PROPERTY_COPY_SET = 1 << 4,
|
||||||
|
G_PROPERTY_COPY_GET = 1 << 5,
|
||||||
|
G_PROPERTY_COPY = (G_PROPERTY_COPY_SET | G_PROPERTY_COPY_GET)
|
||||||
|
} GPropertyFlags;
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GType g_property_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
/* general purpose API */
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gchar * g_property_canonicalize_name (const char *name);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GType g_property_get_value_type (GProperty *property);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_is_writable (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_is_readable (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_is_deprecated (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_is_atomic (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_is_copy_set (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_is_copy_get (GProperty *property);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_describe (GProperty *property,
|
||||||
|
const char *nick,
|
||||||
|
const char *blurb);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_range_values (GProperty *property,
|
||||||
|
const GValue *min_value,
|
||||||
|
const GValue *max_value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_get_range_values (GProperty *property,
|
||||||
|
GValue *min_value,
|
||||||
|
GValue *max_value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_range (GProperty *property,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_get_range (GProperty *property,
|
||||||
|
...);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_default_value (GProperty *property,
|
||||||
|
const GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_default (GProperty *property,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_override_default_value (GProperty *property,
|
||||||
|
GType class_gtype,
|
||||||
|
const GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_override_default (GProperty *property,
|
||||||
|
GType class_gtype,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_get_default_value_for_type (GProperty *property,
|
||||||
|
GType gtype,
|
||||||
|
GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_get_default_value (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_get_default (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
...);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_prerequisite (GProperty *property,
|
||||||
|
GType gtype);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_validate (GProperty *property,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_validate_value (GProperty *property,
|
||||||
|
GValue *value);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_value (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
const GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_get_value (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_set (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_get (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GPropertyCollectFlags:
|
||||||
|
* @G_PROPERTY_COLLECT_NONE: No flags
|
||||||
|
* @G_PROPERTY_COLLECT_COPY: Make a copy when collecting pointer
|
||||||
|
* locations for boxed and string values
|
||||||
|
* @G_PROPERTY_COLLECT_REF: Take a reference when collecting
|
||||||
|
* pointer locations for object values
|
||||||
|
*
|
||||||
|
* Flags to pass to g_property_collect() and g_property_lcopy().
|
||||||
|
*
|
||||||
|
* Since: 2.36
|
||||||
|
*/
|
||||||
|
typedef enum { /*< prefix=G_PROPERTY_COLLECT >*/
|
||||||
|
G_PROPERTY_COLLECT_NONE = 0,
|
||||||
|
|
||||||
|
G_PROPERTY_COLLECT_COPY = 1 << 0,
|
||||||
|
G_PROPERTY_COLLECT_REF = 1 << 1
|
||||||
|
} GPropertyCollectFlags;
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_set_va (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GPropertyCollectFlags flags,
|
||||||
|
va_list *app);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gboolean g_property_get_va (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GPropertyCollectFlags flags,
|
||||||
|
va_list *app);
|
||||||
|
|
||||||
|
typedef void (* GPropertyLockFunc) (GProperty *property,
|
||||||
|
gpointer gobject);
|
||||||
|
|
||||||
|
typedef void (* GPropertyUnlockFunc) (GProperty *property,
|
||||||
|
gpointer gobject);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_set_lock_functions (GProperty *property,
|
||||||
|
GPropertyLockFunc lock_func,
|
||||||
|
GPropertyUnlockFunc unlock_func);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_lock (GProperty *property,
|
||||||
|
gpointer gobject);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void g_property_unlock (GProperty *property,
|
||||||
|
gpointer gobject);
|
||||||
|
|
||||||
|
/* private API */
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
void _g_property_set_installed (GProperty *property,
|
||||||
|
gpointer g_class,
|
||||||
|
GType class_gtype);
|
||||||
|
|
||||||
|
/* per-type specific accessors */
|
||||||
|
typedef gboolean (* GPropertyBooleanSet) (gpointer gobject,
|
||||||
|
gboolean value);
|
||||||
|
typedef gboolean (* GPropertyBooleanGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyIntSet) (gpointer gobject,
|
||||||
|
gint value);
|
||||||
|
typedef gint (* GPropertyIntGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyInt8Set) (gpointer gobject,
|
||||||
|
gint8 value);
|
||||||
|
typedef gint8 (* GPropertyInt8Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyInt16Set) (gpointer gobject,
|
||||||
|
gint16 value);
|
||||||
|
typedef gint16 (* GPropertyInt16Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyInt32Set) (gpointer gobject,
|
||||||
|
gint32 value);
|
||||||
|
typedef gint32 (* GPropertyInt32Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyInt64Set) (gpointer gobject,
|
||||||
|
gint64 value);
|
||||||
|
typedef gint64 (* GPropertyInt64Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyLongSet) (gpointer gobject,
|
||||||
|
glong value);
|
||||||
|
typedef glong (* GPropertyLongGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyUIntSet) (gpointer gobject,
|
||||||
|
guint value);
|
||||||
|
typedef guint (* GPropertyUIntGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyUInt8Set) (gpointer gobject,
|
||||||
|
guint8 value);
|
||||||
|
typedef guint8 (* GPropertyUInt8Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyUInt16Set) (gpointer gobject,
|
||||||
|
guint16 value);
|
||||||
|
typedef guint16 (* GPropertyUInt16Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyUInt32Set) (gpointer gobject,
|
||||||
|
guint32 value);
|
||||||
|
typedef guint32 (* GPropertyUInt32Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyUInt64Set) (gpointer gobject,
|
||||||
|
guint64 value);
|
||||||
|
typedef guint64 (* GPropertyUInt64Get) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyULongSet) (gpointer gobject,
|
||||||
|
gulong value);
|
||||||
|
typedef gulong (* GPropertyULongGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyEnumSet) (gpointer gobject,
|
||||||
|
glong value);
|
||||||
|
typedef glong (* GPropertyEnumGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyFlagsSet) (gpointer gobject,
|
||||||
|
glong value);
|
||||||
|
typedef glong (* GPropertyFlagsGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyFloatSet) (gpointer gobject,
|
||||||
|
gfloat value);
|
||||||
|
typedef gfloat (* GPropertyFloatGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyDoubleSet) (gpointer gobject,
|
||||||
|
gdouble value);
|
||||||
|
typedef gdouble (* GPropertyDoubleGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyStringSet) (gpointer gobject,
|
||||||
|
const char *value);
|
||||||
|
typedef const char * (* GPropertyStringGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyBoxedSet) (gpointer gobject,
|
||||||
|
gpointer value);
|
||||||
|
typedef gpointer (* GPropertyBoxedGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyObjectSet) (gpointer gobject,
|
||||||
|
gpointer value);
|
||||||
|
typedef gpointer (* GPropertyObjectGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyPointerSet) (gpointer gobject,
|
||||||
|
gpointer value);
|
||||||
|
typedef gpointer (* GPropertyPointerGet) (gpointer gobject);
|
||||||
|
|
||||||
|
/* per-type specific constructors */
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_boolean_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyBooleanSet setter,
|
||||||
|
GPropertyBooleanGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_int_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyIntSet setter,
|
||||||
|
GPropertyIntGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_int8_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt8Set setter,
|
||||||
|
GPropertyInt8Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_int16_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt16Set setter,
|
||||||
|
GPropertyInt16Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_int32_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt32Set setter,
|
||||||
|
GPropertyInt32Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_int64_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt64Set setter,
|
||||||
|
GPropertyInt64Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_long_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyLongSet setter,
|
||||||
|
GPropertyLongGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_uint_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUIntSet setter,
|
||||||
|
GPropertyUIntGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_uint8_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt8Set setter,
|
||||||
|
GPropertyUInt8Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_uint16_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt16Set setter,
|
||||||
|
GPropertyUInt16Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_uint32_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt32Set setter,
|
||||||
|
GPropertyUInt32Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_uint64_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt64Set setter,
|
||||||
|
GPropertyUInt64Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_ulong_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyULongSet setter,
|
||||||
|
GPropertyULongGet getter);
|
||||||
|
|
||||||
|
#define g_char_property_new g_int8_property_new
|
||||||
|
#define g_uchar_property_new g_uint8_property_new
|
||||||
|
#define g_unichar_property_new g_uint32_property_new
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_enum_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyEnumSet setter,
|
||||||
|
GPropertyEnumGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_flags_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyFlagsSet setter,
|
||||||
|
GPropertyFlagsGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_float_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyFloatSet setter,
|
||||||
|
GPropertyFloatGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_double_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyDoubleSet setter,
|
||||||
|
GPropertyDoubleGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_string_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyStringSet setter,
|
||||||
|
GPropertyStringGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_boxed_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyBoxedSet setter,
|
||||||
|
GPropertyBoxedGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_object_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyObjectSet setter,
|
||||||
|
GPropertyObjectGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
GParamSpec * g_pointer_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyPointerSet setter,
|
||||||
|
GPropertyPointerGet getter);
|
||||||
|
|
||||||
|
/* accessors generation */
|
||||||
|
#define _G_DECLARE_PROPERTY_GETTER(T_n, t_n, f_t, f_n) f_t t_n##_get_##f_n (T_n *self)
|
||||||
|
|
||||||
|
#define _G_DEFINE_PROPERTY_GETTER_BEGIN(T_n, t_n, f_t, f_n) \
|
||||||
|
{ \
|
||||||
|
GProperty *g_property = NULL; \
|
||||||
|
f_t retval; \
|
||||||
|
\
|
||||||
|
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, t_n##_get_type ()), (f_t) 0); \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
GObjectClass *_self_class; \
|
||||||
|
_self_class = G_OBJECT_GET_CLASS (self); \
|
||||||
|
g_property = (GProperty *) g_object_class_find_property (_self_class, #f_n); \
|
||||||
|
if (G_UNLIKELY (g_property == NULL)) \
|
||||||
|
{ \
|
||||||
|
g_critical (G_STRLOC ": No property " #f_n " found for class %s", \
|
||||||
|
G_OBJECT_TYPE_NAME (self)); \
|
||||||
|
return (f_t) 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (!G_IS_PROPERTY (g_property)) \
|
||||||
|
{ \
|
||||||
|
g_critical (G_STRLOC ": Property " #f_n " is not a GProperty"); \
|
||||||
|
return (f_t) 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (!g_property_is_readable (g_property)) \
|
||||||
|
{ \
|
||||||
|
g_critical (G_STRLOC ": The property " #f_n " is not readable"); \
|
||||||
|
return (f_t) 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (!g_property_get (g_property, self, &retval)) \
|
||||||
|
{ \
|
||||||
|
g_property_get_default (g_property, self, &retval); \
|
||||||
|
return retval; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
{ /* custom code follows */
|
||||||
|
#define _G_DEFINE_PROPERTY_GETTER_END \
|
||||||
|
} /* following custom code */ \
|
||||||
|
\
|
||||||
|
return retval; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define _G_DECLARE_PROPERTY_SETTER(T_n, t_n, f_t, f_n) void t_n##_set_##f_n (T_n *self, f_t value)
|
||||||
|
|
||||||
|
#define _G_DEFINE_PROPERTY_SETTER_BEGIN(T_n, t_n, f_t, f_n) \
|
||||||
|
{ \
|
||||||
|
GProperty *g_property = NULL; \
|
||||||
|
\
|
||||||
|
g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, t_n##_get_type ())); \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
GObjectClass *_self_class; \
|
||||||
|
_self_class = G_OBJECT_GET_CLASS (self); \
|
||||||
|
g_property = (GProperty *) g_object_class_find_property (_self_class, #f_n); \
|
||||||
|
if (G_UNLIKELY (g_property == NULL)) \
|
||||||
|
{ \
|
||||||
|
g_critical (G_STRLOC ": No property " #f_n " found for class %s", G_OBJECT_TYPE_NAME (self)); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (!G_IS_PROPERTY (g_property)) \
|
||||||
|
{ \
|
||||||
|
g_critical (G_STRLOC ": Property " #f_n " is not a GProperty"); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (!g_property_is_writable (g_property)) \
|
||||||
|
{ \
|
||||||
|
g_critical (G_STRLOC ": The property " #f_n " is not writable"); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (!g_property_set (g_property, self, value)) \
|
||||||
|
return; \
|
||||||
|
\
|
||||||
|
{ /* custom code follows */
|
||||||
|
#define _G_DEFINE_PROPERTY_SETTER_END \
|
||||||
|
}/* following custom code */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DECLARE_PROPERTY_GET_SET:
|
||||||
|
* @TypeName: the name of the type, in Camel case
|
||||||
|
* @type_name: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @field_type: the type of the property, which must match the type of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
* @field_name: the name of the property, which must match the name of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
*
|
||||||
|
* Declares the accessor functions for a @field_name property in the
|
||||||
|
* class @TypeName. This macro should only be used in header files.
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
#define G_DECLARE_PROPERTY_GET_SET(T_n, t_n, f_t, f_n) \
|
||||||
|
_G_DECLARE_PROPERTY_SETTER (T_n, t_n, f_t, f_n); \
|
||||||
|
_G_DECLARE_PROPERTY_GETTER (T_n, t_n, f_t, f_n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DECLARE_PROPERTY_GET:
|
||||||
|
* @T_n: the name of the type, in Camel case
|
||||||
|
* @t_n: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @f_t: the type of the property, which must match the type of the field
|
||||||
|
* @f_n: the name of the property, which must match the name of the field
|
||||||
|
*
|
||||||
|
* Declares the getter function for a @f_n property in the @T_n class.
|
||||||
|
*
|
||||||
|
* This macro should only be used in header files.
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
#define G_DECLARE_PROPERTY_GET(T_n, t_n, f_t, f_n) _G_DECLARE_PROPERTY_GETTER (T_n, t_n, f_t, f_n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DECLARE_PROPERTY_SET:
|
||||||
|
* @T_n: the name of the type, in Camel case
|
||||||
|
* @t_n: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @f_t: the type of the property, which must match the type of the field
|
||||||
|
* @f_n: the name of the property, which must match the name of the field
|
||||||
|
*
|
||||||
|
* Declares the setter function for a @f_n property in the @T_n class.
|
||||||
|
*
|
||||||
|
* This macro should only be used in header files.
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
#define G_DECLARE_PROPERTY_SET(T_n, t_n, f_t, f_n) _G_DECLARE_PROPERTY_SETTER (T_n, t_n, f_t, f_n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DEFINE_PROPERTY_SET_WITH_CODE:
|
||||||
|
* @TypeName: the name of the type, in Camel case
|
||||||
|
* @type_name: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @field_type: the type of the property, which must match the type of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
* @field_name: the name of the property, which must match the name of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
* @_C_: C code that should be called after the property has been set
|
||||||
|
*
|
||||||
|
* Defines the setter function for a @field_name property in the
|
||||||
|
* class @TypeName, with the possibility of calling custom code.
|
||||||
|
*
|
||||||
|
* This macro should only be used in C source files.
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* G_DEFINE_PROPERTY_SET_WITH_CODE (ClutterActor, clutter_actor,
|
||||||
|
* int, margin_top,
|
||||||
|
* clutter_actor_queue_redraw (self))
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define G_DEFINE_PROPERTY_SET_WITH_CODE(T_n, t_n, f_t, f_n, _C_) \
|
||||||
|
_G_DECLARE_PROPERTY_SETTER (T_n, t_n, f_t, f_n) \
|
||||||
|
_G_DEFINE_PROPERTY_SETTER_BEGIN (T_n, t_n, f_t, f_n) \
|
||||||
|
{ _C_; } \
|
||||||
|
_G_DEFINE_PROPERTY_SETTER_END
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DEFINE_PROPERTY_GET_WITH_CODE:
|
||||||
|
* @T_n: the name of the type, in Camel case
|
||||||
|
* @t_n: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @f_t: the type of the property, which must match the type of the
|
||||||
|
* field in the @T_n<!-- -->Private structure
|
||||||
|
* @f_n: the name of the property, which must match the name of the
|
||||||
|
* field in the @T_n<!-- -->Private structure
|
||||||
|
* @_C_: C code to be called after the property has been retrieved
|
||||||
|
*
|
||||||
|
* Defines the getter function for a @f_n property in the
|
||||||
|
* class @T_n, with the possibility of calling custom code.
|
||||||
|
*
|
||||||
|
* This macro should only be used in C source files.
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
#define G_DEFINE_PROPERTY_GET_WITH_CODE(T_n, t_n, f_t, f_n, _C_) \
|
||||||
|
_G_DECLARE_PROPERTY_GETTER (T_n, t_n, f_t, f_n) \
|
||||||
|
_G_DEFINE_PROPERTY_GETTER_BEGIN (T_n, t_n, f_t, f_n) \
|
||||||
|
{ _C_; } \
|
||||||
|
_G_DEFINE_PROPERTY_GETTER_END
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DEFINE_PROPERTY_SET:
|
||||||
|
* @TypeName: the name of the type, in Camel case
|
||||||
|
* @type_name: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @field_type: the type of the property, which must match the type of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
* @field_name: the name of the property, which must match the name of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
*
|
||||||
|
* Defines the setter function for a @field_name property in the
|
||||||
|
* class @TypeName. This macro should only be used in C source files.
|
||||||
|
*
|
||||||
|
* See also: %G_DEFINE_PROPERTY_SET_WITH_CODE
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
#define G_DEFINE_PROPERTY_SET(T_n, t_n, f_t, f_n) G_DEFINE_PROPERTY_SET_WITH_CODE (T_n, t_n, f_t, f_n, ;)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DEFINE_PROPERTY_GET:
|
||||||
|
* @TypeName: the name of the type, in Camel case
|
||||||
|
* @type_name: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @field_type: the type of the property, which must match the type of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
* @field_name: the name of the property, which must match the name of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
*
|
||||||
|
* Defines the getter function for a @field_name property in the
|
||||||
|
* class @TypeName. This macro should only be used in C source files.
|
||||||
|
*
|
||||||
|
* See also %G_DEFINE_PROPERTY_GET_WITH_CODE.
|
||||||
|
*/
|
||||||
|
#define G_DEFINE_PROPERTY_GET(T_n, t_n, f_t, f_n) G_DEFINE_PROPERTY_GET_WITH_CODE (T_n, t_n, f_t, f_n, ;)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G_DEFINE_PROPERTY_GET_SET:
|
||||||
|
* @T_n: the name of the type, in Camel case
|
||||||
|
* @t_n: the name of the type, in lowercase, with words separated by '_'
|
||||||
|
* @f_t: the type of the property, which must match the type of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
* @f_n: the name of the property, which must match the name of the
|
||||||
|
* field in the @TypeName<!-- -->Private structure
|
||||||
|
*
|
||||||
|
* Defines the accessor functions for a @f_n property in the class @T_n.
|
||||||
|
*
|
||||||
|
* This macro should only be used in C source files, for instance:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* G_DEFINE_PROPERTY_GET_SET (ClutterActor, clutter_actor, int, margin_top)
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* will synthesize the equivalent of the following code:
|
||||||
|
*
|
||||||
|
* |[
|
||||||
|
* void
|
||||||
|
* clutter_actor_set_margin_top (ClutterActor *self,
|
||||||
|
* int value)
|
||||||
|
* {
|
||||||
|
* ClutterActorPrivate *priv;
|
||||||
|
*
|
||||||
|
* g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, clutter_actor_get_type ()));
|
||||||
|
*
|
||||||
|
* priv = self->priv;
|
||||||
|
*
|
||||||
|
* if (priv->margin_top == value)
|
||||||
|
* return;
|
||||||
|
*
|
||||||
|
* priv->value = value;
|
||||||
|
*
|
||||||
|
* g_object_notify (G_OBJECT (self), "margin-top");
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* int
|
||||||
|
* clutter_actor_get_margin_top (ClutterActor *self)
|
||||||
|
* {
|
||||||
|
* g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, clutter_actor_get_type ()), 0);
|
||||||
|
*
|
||||||
|
* return self->priv->margin_top;
|
||||||
|
* }
|
||||||
|
* ]|
|
||||||
|
*
|
||||||
|
* This macro will generate both the setter and getter functions; if the
|
||||||
|
* property is not readable and writable, the generated functions will
|
||||||
|
* warn at run-time.
|
||||||
|
*
|
||||||
|
* For greater control on the setter and getter implementation, see also the
|
||||||
|
* %G_DEFINE_PROPERTY_GET and %G_DEFINE_PROPERTY_SET macros, along with their
|
||||||
|
* %G_DEFINE_PROPERTY_GET_WITH_CODE and %G_DEFINE_PROPERTY_SET_WITH_CODE
|
||||||
|
* variants.
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
#define G_DEFINE_PROPERTY_GET_SET(T_n, t_n, f_t, f_n) \
|
||||||
|
G_DEFINE_PROPERTY_GET (T_n, t_n, f_t, f_n) \
|
||||||
|
G_DEFINE_PROPERTY_SET (T_n, t_n, f_t, f_n)
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __G_PROPERTY_H__ */
|
103
gobject/gtype.c
103
gobject/gtype.c
@ -4501,16 +4501,82 @@ g_type_class_add_private (gpointer g_class,
|
|||||||
G_WRITE_UNLOCK (&type_rw_lock);
|
G_WRITE_UNLOCK (&type_rw_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpointer
|
static gssize
|
||||||
g_type_instance_get_private (GTypeInstance *instance,
|
lookup_instance_private_offset (GTypeClass *class,
|
||||||
GType private_type)
|
GType private_type)
|
||||||
{
|
{
|
||||||
TypeNode *instance_node;
|
TypeNode *instance_node;
|
||||||
TypeNode *private_node;
|
TypeNode *private_node;
|
||||||
TypeNode *parent_node;
|
TypeNode *parent_node;
|
||||||
GTypeClass *class;
|
|
||||||
gsize offset;
|
gsize offset;
|
||||||
|
|
||||||
|
g_return_val_if_fail (class != NULL, -1);
|
||||||
|
|
||||||
|
instance_node = lookup_type_node_I (class->g_type);
|
||||||
|
if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
|
||||||
|
{
|
||||||
|
g_warning ("class of invalid non-instantiatable type `%s'",
|
||||||
|
type_descriptive_name_I (class->g_type));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private_node = lookup_type_node_I (private_type);
|
||||||
|
if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node)))
|
||||||
|
{
|
||||||
|
g_warning ("attempt to retrieve private data for invalid type '%s'",
|
||||||
|
type_descriptive_name_I (private_type));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = ALIGN_STRUCT (instance_node->data->instance.instance_size);
|
||||||
|
|
||||||
|
if (NODE_PARENT_TYPE (private_node))
|
||||||
|
{
|
||||||
|
parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
|
||||||
|
g_assert (parent_node->data && NODE_REFCOUNT (parent_node) > 0);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (private_node->data->instance.private_size == parent_node->data->instance.private_size))
|
||||||
|
{
|
||||||
|
g_warning ("g_type_class_get_instance_private_offset() requires a "
|
||||||
|
"prior call to g_type_class_add_private()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += ALIGN_STRUCT (parent_node->data->instance.private_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
gssize
|
||||||
|
g_type_class_get_instance_private_offset (gpointer g_class,
|
||||||
|
GType private_type)
|
||||||
|
{
|
||||||
|
gssize offset;
|
||||||
|
|
||||||
|
g_return_val_if_fail (g_class != NULL, -1);
|
||||||
|
|
||||||
|
/* unlike with g_type_instance_get_private(), we need to acquire the
|
||||||
|
* read lock here because we may be called during class initialization
|
||||||
|
* type, which means that nodes may not be filled yet.
|
||||||
|
*/
|
||||||
|
G_READ_LOCK (&type_rw_lock);
|
||||||
|
|
||||||
|
offset = lookup_instance_private_offset (g_class, private_type);
|
||||||
|
|
||||||
|
G_READ_UNLOCK (&type_rw_lock);
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
g_type_instance_get_private (GTypeInstance *instance,
|
||||||
|
GType private_type)
|
||||||
|
{
|
||||||
|
GTypeClass *class;
|
||||||
|
TypeNode *instance_node;
|
||||||
|
gssize offset;
|
||||||
|
|
||||||
g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
|
g_return_val_if_fail (instance != NULL && instance->g_class != NULL, NULL);
|
||||||
|
|
||||||
/* while instances are initialized, their class pointers change,
|
/* while instances are initialized, their class pointers change,
|
||||||
@ -4524,15 +4590,7 @@ g_type_instance_get_private (GTypeInstance *instance,
|
|||||||
if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
|
if (G_UNLIKELY (!instance_node || !instance_node->is_instantiatable))
|
||||||
{
|
{
|
||||||
g_warning ("instance of invalid non-instantiatable type `%s'",
|
g_warning ("instance of invalid non-instantiatable type `%s'",
|
||||||
type_descriptive_name_I (instance->g_class->g_type));
|
type_descriptive_name_I (class->g_type));
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private_node = lookup_type_node_I (private_type);
|
|
||||||
if (G_UNLIKELY (!private_node || !NODE_IS_ANCESTOR (private_node, instance_node)))
|
|
||||||
{
|
|
||||||
g_warning ("attempt to retrieve private data for invalid type '%s'",
|
|
||||||
type_descriptive_name_I (private_type));
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4542,22 +4600,9 @@ g_type_instance_get_private (GTypeInstance *instance,
|
|||||||
* and node->data->instance.private_size are not going to be changed.
|
* and node->data->instance.private_size are not going to be changed.
|
||||||
* for any of the relevant types.
|
* for any of the relevant types.
|
||||||
*/
|
*/
|
||||||
|
offset = lookup_instance_private_offset (class, private_type);
|
||||||
offset = ALIGN_STRUCT (instance_node->data->instance.instance_size);
|
if (offset < 0)
|
||||||
|
return NULL;
|
||||||
if (NODE_PARENT_TYPE (private_node))
|
|
||||||
{
|
|
||||||
parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
|
|
||||||
g_assert (parent_node->data && NODE_REFCOUNT (parent_node) > 0);
|
|
||||||
|
|
||||||
if (G_UNLIKELY (private_node->data->instance.private_size == parent_node->data->instance.private_size))
|
|
||||||
{
|
|
||||||
g_warning ("g_type_instance_get_private() requires a prior call to g_type_class_add_private()");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += ALIGN_STRUCT (parent_node->data->instance.private_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return G_STRUCT_MEMBER_P (instance, offset);
|
return G_STRUCT_MEMBER_P (instance, offset);
|
||||||
}
|
}
|
||||||
|
@ -1264,6 +1264,10 @@ gpointer g_type_class_get_private (GTypeClass *klass,
|
|||||||
GLIB_AVAILABLE_IN_2_34
|
GLIB_AVAILABLE_IN_2_34
|
||||||
void g_type_ensure (GType type);
|
void g_type_ensure (GType type);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_36
|
||||||
|
gssize g_type_class_get_instance_private_offset (gpointer g_class,
|
||||||
|
GType private_type);
|
||||||
|
|
||||||
/* --- GType boilerplate --- */
|
/* --- GType boilerplate --- */
|
||||||
/**
|
/**
|
||||||
* G_DEFINE_TYPE:
|
* G_DEFINE_TYPE:
|
||||||
|
3
gobject/tests/.gitignore
vendored
3
gobject/tests/.gitignore
vendored
@ -1,7 +1,10 @@
|
|||||||
|
autoproperties
|
||||||
binding
|
binding
|
||||||
boxed
|
boxed
|
||||||
dynamictests
|
dynamictests
|
||||||
enums
|
enums
|
||||||
|
gproperty-example-base
|
||||||
|
gproperty-example-derived
|
||||||
ifaceproperties
|
ifaceproperties
|
||||||
param
|
param
|
||||||
properties
|
properties
|
||||||
|
@ -11,8 +11,8 @@ else
|
|||||||
glib_genmarshal=$(top_builddir)/gobject/glib-genmarshal
|
glib_genmarshal=$(top_builddir)/gobject/glib-genmarshal
|
||||||
endif
|
endif
|
||||||
|
|
||||||
noinst_PROGRAMS = $(TEST_PROGS)
|
|
||||||
LDADD = ../libgobject-2.0.la $(top_builddir)/gthread/libgthread-2.0.la $(top_builddir)/glib/libglib-2.0.la
|
LDADD = ../libgobject-2.0.la $(top_builddir)/gthread/libgthread-2.0.la $(top_builddir)/glib/libglib-2.0.la
|
||||||
|
noinst_PROGRAMS = $(TEST_PROGS) $(SAMPLE_PROGS)
|
||||||
|
|
||||||
TEST_PROGS += \
|
TEST_PROGS += \
|
||||||
qdata \
|
qdata \
|
||||||
@ -26,7 +26,14 @@ TEST_PROGS += \
|
|||||||
properties \
|
properties \
|
||||||
reference \
|
reference \
|
||||||
ifaceproperties \
|
ifaceproperties \
|
||||||
valuearray
|
valuearray \
|
||||||
|
autoproperties \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
SAMPLE_PROGS = \
|
||||||
|
gproperty-example-base \
|
||||||
|
gproperty-example-derived \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
signals_SOURCES = signals.c marshalers.c
|
signals_SOURCES = signals.c marshalers.c
|
||||||
|
|
||||||
|
596
gobject/tests/autoproperties.c
Normal file
596
gobject/tests/autoproperties.c
Normal file
@ -0,0 +1,596 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
/* XXX: yuck, but a lot of the functions are macro-ized */
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
|
typedef struct _TestObject TestObject;
|
||||||
|
typedef struct _TestObjectPrivate TestObjectPrivate;
|
||||||
|
typedef struct _TestObjectClass TestObjectClass;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TEST_ENUM_VALUE_FOO = -1,
|
||||||
|
TEST_ENUM_VALUE_BAR = 0,
|
||||||
|
TEST_ENUM_VALUE_BAZ = 1
|
||||||
|
} TestEnumValue;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TEST_FLAGS_VALUE_FOO = 0,
|
||||||
|
TEST_FLAGS_VALUE_BAR = 1 << 0,
|
||||||
|
TEST_FLAGS_VALUE_BAZ = 1 << 1
|
||||||
|
} TestFlagsValue;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x, y, width, height;
|
||||||
|
|
||||||
|
int ref_count;
|
||||||
|
} TestBoxed;
|
||||||
|
|
||||||
|
struct _TestObject
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
TestObjectPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestObjectClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestObjectPrivate
|
||||||
|
{
|
||||||
|
gint dummy;
|
||||||
|
|
||||||
|
gint foo;
|
||||||
|
|
||||||
|
gboolean bar;
|
||||||
|
|
||||||
|
gchar *str;
|
||||||
|
gboolean str_set;
|
||||||
|
|
||||||
|
gint8 single_byte;
|
||||||
|
gint16 double_byte;
|
||||||
|
gint32 four_bytes;
|
||||||
|
|
||||||
|
float width;
|
||||||
|
double x_align;
|
||||||
|
|
||||||
|
TestEnumValue enum_value;
|
||||||
|
TestFlagsValue flags_value;
|
||||||
|
|
||||||
|
TestBoxed *boxed;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_FOO,
|
||||||
|
PROP_BAR,
|
||||||
|
PROP_STR,
|
||||||
|
PROP_STR_SET,
|
||||||
|
PROP_BAZ,
|
||||||
|
PROP_SINGLE_BYTE,
|
||||||
|
PROP_DOUBLE_BYTE,
|
||||||
|
PROP_FOUR_BYTES,
|
||||||
|
PROP_WIDTH,
|
||||||
|
PROP_X_ALIGN,
|
||||||
|
PROP_ENUM_VALUE,
|
||||||
|
PROP_FLAGS_VALUE,
|
||||||
|
PROP_BOXED,
|
||||||
|
|
||||||
|
LAST_PROP
|
||||||
|
};
|
||||||
|
|
||||||
|
GType test_enum_value_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
GType
|
||||||
|
test_enum_value_get_type (void)
|
||||||
|
{
|
||||||
|
static volatile gsize g_define_type_id__volatile = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||||
|
{
|
||||||
|
static const GEnumValue values[] = {
|
||||||
|
{ TEST_ENUM_VALUE_FOO, "TEST_ENUM_VALUE_FOO", "foo" },
|
||||||
|
{ TEST_ENUM_VALUE_BAR, "TEST_ENUM_VALUE_BAR", "bar" },
|
||||||
|
{ TEST_ENUM_VALUE_BAZ, "TEST_ENUM_VALUE_BAZ", "baz" },
|
||||||
|
{ 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
GType g_define_type_id =
|
||||||
|
g_enum_register_static (g_intern_static_string ("TestEnumValue"), values);
|
||||||
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_define_type_id__volatile;
|
||||||
|
}
|
||||||
|
|
||||||
|
GType test_flags_value_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
GType
|
||||||
|
test_flags_value_get_type (void)
|
||||||
|
{
|
||||||
|
static volatile gsize g_define_type_id__volatile = 0;
|
||||||
|
|
||||||
|
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||||
|
{
|
||||||
|
static const GFlagsValue values[] = {
|
||||||
|
{ TEST_FLAGS_VALUE_FOO, "TEST_FLAGS_VALUE_FOO", "foo" },
|
||||||
|
{ TEST_FLAGS_VALUE_BAR, "TEST_FLAGS_VALUE_BAR", "bar" },
|
||||||
|
{ TEST_FLAGS_VALUE_BAZ, "TEST_FLAGS_VALUE_BAZ", "baz" },
|
||||||
|
{ 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
GType g_define_type_id =
|
||||||
|
g_flags_register_static (g_intern_static_string ("TestFlagsValue"), values);
|
||||||
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_define_type_id__volatile;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TestBoxed *
|
||||||
|
test_boxed_new (int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
TestBoxed *retval = g_new (TestBoxed, 1);
|
||||||
|
|
||||||
|
retval->x = x;
|
||||||
|
retval->y = y;
|
||||||
|
retval->width = width;
|
||||||
|
retval->height = height;
|
||||||
|
retval->ref_count = 1;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
test_boxed_copy (gpointer data)
|
||||||
|
{
|
||||||
|
if (data != NULL)
|
||||||
|
{
|
||||||
|
TestBoxed *boxed = data;
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("*** copy of boxed %p (ref count: %d) ***\n", boxed, boxed->ref_count);
|
||||||
|
|
||||||
|
if (boxed->ref_count < 0)
|
||||||
|
return test_boxed_new (boxed->x, boxed->y, boxed->width, boxed->height);
|
||||||
|
|
||||||
|
boxed->ref_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_boxed_free (gpointer data)
|
||||||
|
{
|
||||||
|
if (data != NULL)
|
||||||
|
{
|
||||||
|
TestBoxed *boxed = data;
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("*** free of boxed %p (ref count: %d) ***\n", boxed, boxed->ref_count);
|
||||||
|
|
||||||
|
if (boxed->ref_count < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
boxed->ref_count -= 1;
|
||||||
|
|
||||||
|
if (boxed->ref_count == 0)
|
||||||
|
g_free (boxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GType test_boxed_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_BOXED_TYPE (TestBoxed, test_boxed, test_boxed_copy, test_boxed_free)
|
||||||
|
|
||||||
|
static GParamSpec *test_object_properties[LAST_PROP] = { NULL, };
|
||||||
|
|
||||||
|
GType test_object_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, int, foo)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gboolean, bar)
|
||||||
|
G_DEFINE_PROPERTY_GET (TestObject, test_object, gboolean, str_set)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gint8, single_byte)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gint16, double_byte)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gint32, four_bytes)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, float, width)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, double, x_align)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, TestEnumValue, enum_value)
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, TestFlagsValue, flags_value)
|
||||||
|
|
||||||
|
G_DEFINE_PROPERTY_SET (TestObject, test_object, const TestBoxed *, boxed)
|
||||||
|
|
||||||
|
void
|
||||||
|
test_object_get_boxed (TestObject *self,
|
||||||
|
TestBoxed *value)
|
||||||
|
{
|
||||||
|
TestBoxed *boxed;
|
||||||
|
|
||||||
|
g_property_get (G_PROPERTY (test_object_properties[PROP_BOXED]), self, &boxed);
|
||||||
|
|
||||||
|
/* make sure that g_property_get() didn't copy/ref the pointer */
|
||||||
|
g_assert (boxed == self->priv->boxed);
|
||||||
|
g_assert_cmpint (boxed->ref_count, ==, self->priv->boxed->ref_count);
|
||||||
|
|
||||||
|
*value = *boxed;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
test_object_set_str (TestObject *self,
|
||||||
|
const gchar *value)
|
||||||
|
{
|
||||||
|
TestObjectPrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (self, test_object_get_type ()), FALSE);
|
||||||
|
|
||||||
|
priv = self->priv;
|
||||||
|
|
||||||
|
if (g_strcmp0 (priv->str, value) == 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_free (priv->str);
|
||||||
|
priv->str = g_strdup (value);
|
||||||
|
|
||||||
|
if (priv->str != NULL)
|
||||||
|
priv->str_set = TRUE;
|
||||||
|
else
|
||||||
|
priv->str_set = FALSE;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), test_object_properties[PROP_STR_SET]);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_PROPERTY_GET (TestObject, test_object, const gchar *, str);
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_object_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
TestObjectPrivate *priv = ((TestObject *) gobject)->priv;
|
||||||
|
|
||||||
|
test_boxed_free (priv->boxed);
|
||||||
|
g_free (priv->str);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_object_class_init (TestObjectClass *klass)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = test_object_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (TestObjectPrivate));
|
||||||
|
|
||||||
|
test_object_properties[PROP_FOO] =
|
||||||
|
g_int_property_new ("foo", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, foo),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_range (G_PROPERTY (test_object_properties[PROP_FOO]), -1, 100);
|
||||||
|
g_property_set_default (G_PROPERTY (test_object_properties[PROP_FOO]), 50);
|
||||||
|
|
||||||
|
test_object_properties[PROP_BAR] =
|
||||||
|
g_boolean_property_new ("bar", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, bar),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_STR] =
|
||||||
|
g_string_property_new ("str", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, str),
|
||||||
|
(GPropertyStringSet) test_object_set_str,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_STR_SET] =
|
||||||
|
g_boolean_property_new ("str-set", G_PROPERTY_READABLE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, str_set),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_BAZ] =
|
||||||
|
g_int_property_new ("baz", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, foo),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_SINGLE_BYTE] =
|
||||||
|
g_int8_property_new ("single-byte", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, single_byte),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_DOUBLE_BYTE] =
|
||||||
|
g_int16_property_new ("double-byte", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, double_byte),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_FOUR_BYTES] =
|
||||||
|
g_int32_property_new ("four-bytes", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, four_bytes),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_WIDTH] =
|
||||||
|
g_float_property_new ("width", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, width),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_range (G_PROPERTY (test_object_properties[PROP_WIDTH]), 0.0, G_MAXFLOAT);
|
||||||
|
|
||||||
|
test_object_properties[PROP_X_ALIGN] =
|
||||||
|
g_double_property_new ("x-align", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, x_align),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_range (G_PROPERTY (test_object_properties[PROP_X_ALIGN]), 0.0, 1.0);
|
||||||
|
g_property_set_default (G_PROPERTY (test_object_properties[PROP_X_ALIGN]), 0.5);
|
||||||
|
|
||||||
|
test_object_properties[PROP_ENUM_VALUE] =
|
||||||
|
g_enum_property_new ("enum-value", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, enum_value),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_ENUM_VALUE]),
|
||||||
|
test_enum_value_get_type ());
|
||||||
|
g_property_set_default (G_PROPERTY (test_object_properties[PROP_ENUM_VALUE]),
|
||||||
|
TEST_ENUM_VALUE_BAR);
|
||||||
|
|
||||||
|
test_object_properties[PROP_FLAGS_VALUE] =
|
||||||
|
g_flags_property_new ("flags-value", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, flags_value),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_FLAGS_VALUE]),
|
||||||
|
test_flags_value_get_type ());
|
||||||
|
g_property_set_default (G_PROPERTY (test_object_properties[PROP_FLAGS_VALUE]),
|
||||||
|
TEST_FLAGS_VALUE_FOO);
|
||||||
|
|
||||||
|
test_object_properties[PROP_BOXED] =
|
||||||
|
g_boxed_property_new ("boxed", G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, boxed),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_BOXED]),
|
||||||
|
test_boxed_get_type ());
|
||||||
|
|
||||||
|
g_object_class_install_properties (G_OBJECT_CLASS (klass),
|
||||||
|
G_N_ELEMENTS (test_object_properties),
|
||||||
|
test_object_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_object_init (TestObject *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, test_object_get_type (), TestObjectPrivate);
|
||||||
|
|
||||||
|
g_property_get_default (G_PROPERTY (test_object_properties[PROP_FOO]),
|
||||||
|
self,
|
||||||
|
&(self->priv->foo));
|
||||||
|
g_property_get_default (G_PROPERTY (test_object_properties[PROP_X_ALIGN]),
|
||||||
|
self,
|
||||||
|
&(self->priv->x_align));
|
||||||
|
g_property_get_default (G_PROPERTY (test_object_properties[PROP_ENUM_VALUE]),
|
||||||
|
self,
|
||||||
|
&(self->priv->enum_value));
|
||||||
|
g_property_get_default (G_PROPERTY (test_object_properties[PROP_FLAGS_VALUE]),
|
||||||
|
self,
|
||||||
|
&(self->priv->flags_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_base (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
|
||||||
|
g_assert (G_TYPE_CHECK_INSTANCE_TYPE (t, test_object_get_type ()));
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_constructor (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (),
|
||||||
|
"str", "Hello, World!",
|
||||||
|
"x-align", 1.0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert (G_TYPE_CHECK_INSTANCE_TYPE (t, test_object_get_type ()));
|
||||||
|
g_assert_cmpstr (test_object_get_str (t), ==, "Hello, World!");
|
||||||
|
g_assert_cmpfloat (test_object_get_x_align (t), ==, 1.0);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TestObject TestDerived;
|
||||||
|
typedef TestObjectClass TestDerivedClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (TestDerived, test_derived, test_object_get_type ())
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_derived_class_init (TestDerivedClass *klass)
|
||||||
|
{
|
||||||
|
g_object_class_override_property_default (G_OBJECT_CLASS (klass), "foo", -1);
|
||||||
|
g_object_class_override_property_default (G_OBJECT_CLASS (klass), "enum-value", TEST_ENUM_VALUE_BAZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_derived_init (TestDerived *self)
|
||||||
|
{
|
||||||
|
GValue value = { 0, };
|
||||||
|
|
||||||
|
g_value_init (&value, g_property_get_value_type (G_PROPERTY (test_object_properties[PROP_FOO])));
|
||||||
|
g_property_get_default_value_for_type (G_PROPERTY (test_object_properties[PROP_FOO]),
|
||||||
|
test_derived_get_type (),
|
||||||
|
&value);
|
||||||
|
|
||||||
|
g_assert_cmpint (g_value_get_int (&value), !=, 50);
|
||||||
|
g_assert_cmpint (g_value_get_int (&value), ==, -1);
|
||||||
|
|
||||||
|
test_object_set_foo ((TestObject *) self, g_value_get_int (&value));
|
||||||
|
|
||||||
|
g_value_unset (&value);
|
||||||
|
|
||||||
|
test_object_set_enum_value ((TestObject *) self, TEST_ENUM_VALUE_BAZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_default (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
|
||||||
|
g_assert (g_type_is_a (G_OBJECT_TYPE (t), test_object_get_type ()));
|
||||||
|
g_assert_cmpint (test_object_get_foo (t), ==, 50);
|
||||||
|
g_assert_cmpfloat (test_object_get_x_align (t), ==, 0.5f);
|
||||||
|
g_assert (test_object_get_enum_value (t) == TEST_ENUM_VALUE_BAR);
|
||||||
|
g_assert (test_object_get_flags_value (t) == TEST_FLAGS_VALUE_FOO);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
|
||||||
|
t = g_object_new (test_derived_get_type (), NULL);
|
||||||
|
|
||||||
|
g_assert (g_type_is_a (G_OBJECT_TYPE (t), test_object_get_type ()));
|
||||||
|
g_assert (g_type_is_a (G_OBJECT_TYPE (t), test_derived_get_type ()));
|
||||||
|
g_assert_cmpint (test_object_get_foo (t), ==, -1);
|
||||||
|
g_assert (test_object_get_enum_value (t) == TEST_ENUM_VALUE_BAZ);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_range (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
GProperty *p;
|
||||||
|
gint i_min, i_max;
|
||||||
|
gdouble d_min, d_max;
|
||||||
|
|
||||||
|
p = (GProperty *) g_object_class_find_property (G_OBJECT_GET_CLASS (t), "foo");
|
||||||
|
g_assert (G_IS_PROPERTY (p));
|
||||||
|
|
||||||
|
g_property_get_range (p, &i_min, &i_max);
|
||||||
|
g_assert_cmpint (i_min, ==, -1);
|
||||||
|
g_assert_cmpint (i_max, ==, 100);
|
||||||
|
|
||||||
|
p = (GProperty *) g_object_class_find_property (G_OBJECT_GET_CLASS (t), "x-align");
|
||||||
|
g_assert (G_IS_PROPERTY (p));
|
||||||
|
|
||||||
|
g_property_get_range (p, &d_min, &d_max);
|
||||||
|
g_assert_cmpfloat (d_min, ==, 0.0);
|
||||||
|
g_assert_cmpfloat (d_max, ==, 1.0);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_accessors (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
|
||||||
|
test_object_set_foo (t, 42);
|
||||||
|
g_assert_cmpint (test_object_get_foo (t), ==, 42);
|
||||||
|
|
||||||
|
test_object_set_str (t, "hello");
|
||||||
|
g_assert_cmpstr (test_object_get_str (t), ==, "hello");
|
||||||
|
g_assert (test_object_get_str_set (t));
|
||||||
|
|
||||||
|
g_assert (!test_object_get_bar (t));
|
||||||
|
|
||||||
|
test_object_set_single_byte (t, 64);
|
||||||
|
g_assert_cmpint (test_object_get_single_byte (t), ==, 64);
|
||||||
|
|
||||||
|
test_object_set_double_byte (t, G_MAXINT16 / 2);
|
||||||
|
g_assert_cmpint (test_object_get_double_byte (t), ==, G_MAXINT16 / 2);
|
||||||
|
|
||||||
|
test_object_set_four_bytes (t, 47);
|
||||||
|
g_assert_cmpint (test_object_get_four_bytes (t), ==, 47);
|
||||||
|
|
||||||
|
test_object_set_width (t, 640);
|
||||||
|
g_assert_cmpfloat (test_object_get_width (t), ==, 640.0f);
|
||||||
|
|
||||||
|
test_object_set_x_align (t, 1.0);
|
||||||
|
g_assert_cmpfloat (test_object_get_x_align (t), ==, 1.0);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_validate (void)
|
||||||
|
{
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT|G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
test_object_set_foo (t, 101);
|
||||||
|
g_object_unref (t);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
|
||||||
|
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT|G_TEST_TRAP_SILENCE_STDERR))
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
test_object_set_foo (t, -10);
|
||||||
|
g_object_unref (t);
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
g_test_trap_assert_failed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_object_set (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
TestBoxed boxed = { 0, 0, 200, 200, -1 };
|
||||||
|
TestBoxed check;
|
||||||
|
|
||||||
|
g_object_set (t,
|
||||||
|
"foo", 42,
|
||||||
|
"bar", TRUE,
|
||||||
|
"flags-value", (TEST_FLAGS_VALUE_BAR | TEST_FLAGS_VALUE_BAZ),
|
||||||
|
"boxed", &boxed,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_assert_cmpint (test_object_get_foo (t), ==, 42);
|
||||||
|
g_assert (test_object_get_bar (t));
|
||||||
|
g_assert ((test_object_get_flags_value (t) & TEST_FLAGS_VALUE_BAZ) != 0);
|
||||||
|
test_object_get_boxed (t, &check);
|
||||||
|
g_assert_cmpint (boxed.y, ==, check.y);
|
||||||
|
g_assert_cmpint (boxed.width, ==, check.width);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
autoproperties_object_get (void)
|
||||||
|
{
|
||||||
|
TestObject *t = g_object_new (test_object_get_type (), NULL);
|
||||||
|
TestBoxed *boxed;
|
||||||
|
gdouble x_align;
|
||||||
|
gfloat width;
|
||||||
|
|
||||||
|
g_object_get (t, "x-align", &x_align, "width", &width, "boxed", &boxed, NULL);
|
||||||
|
g_assert_cmpfloat (x_align, ==, 0.5);
|
||||||
|
g_assert_cmpfloat (width, ==, 0);
|
||||||
|
g_assert (boxed == NULL);
|
||||||
|
|
||||||
|
g_object_unref (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||||
|
|
||||||
|
g_test_add_func ("/auto-properties/base", autoproperties_base);
|
||||||
|
g_test_add_func ("/auto-properties/constructor", autoproperties_constructor);
|
||||||
|
g_test_add_func ("/auto-properties/default", autoproperties_default);
|
||||||
|
g_test_add_func ("/auto-properties/range", autoproperties_range);
|
||||||
|
g_test_add_func ("/auto-properties/accessors", autoproperties_accessors);
|
||||||
|
g_test_add_func ("/auto-properties/validate", autoproperties_validate);
|
||||||
|
g_test_add_func ("/auto-properties/object-set", autoproperties_object_set);
|
||||||
|
g_test_add_func ("/auto-properties/object-get", autoproperties_object_get);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
146
gobject/tests/gproperty-example-base.c
Normal file
146
gobject/tests/gproperty-example-base.c
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#define TEST_TYPE_FILE (test_file_get_type ())
|
||||||
|
#define TEST_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_FILE, TestFile))
|
||||||
|
#define TEST_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_FILE))
|
||||||
|
|
||||||
|
typedef struct _TestFile TestFile;
|
||||||
|
typedef struct _TestFilePrivate TestFilePrivate;
|
||||||
|
typedef struct _TestFileClass TestFileClass;
|
||||||
|
|
||||||
|
struct _TestFile
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
TestFilePrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestFileClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestFilePrivate
|
||||||
|
{
|
||||||
|
gchar *path;
|
||||||
|
|
||||||
|
gint64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType test_file_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (TestFile, test_file, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
enum { PROP_0, PROP_PATH, PROP_SIZE, LAST_PROP };
|
||||||
|
|
||||||
|
static GParamSpec *test_file_properties[LAST_PROP] = { 0, };
|
||||||
|
|
||||||
|
/* for -Wmissing-prototypes */
|
||||||
|
G_DECLARE_PROPERTY_GET_SET (TestFile, test_file, const gchar *, path)
|
||||||
|
|
||||||
|
G_DEFINE_PROPERTY_GET (TestFile, test_file, const gchar *, path)
|
||||||
|
|
||||||
|
void
|
||||||
|
test_file_set_path (TestFile *self,
|
||||||
|
const gchar *value)
|
||||||
|
{
|
||||||
|
GStatBuf s_buf;
|
||||||
|
|
||||||
|
g_return_if_fail (TEST_IS_FILE (self));
|
||||||
|
g_return_if_fail (value != NULL && *value != '\0');
|
||||||
|
|
||||||
|
if (g_strcmp0 (value, self->priv->path) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_stat (value, &s_buf) == -1)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
g_warning ("Unable to access the path: %s", g_strerror (saved_errno));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv->size = (gint64) s_buf.st_size;
|
||||||
|
|
||||||
|
g_free (self->priv->path);
|
||||||
|
self->priv->path = g_strdup (value);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), test_file_properties[PROP_SIZE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for -Wmissing-prototypes */
|
||||||
|
G_DECLARE_PROPERTY_GET (TestFile, test_file, gint64, size)
|
||||||
|
|
||||||
|
G_DEFINE_PROPERTY_GET (TestFile, test_file, gint64, size)
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
TestFilePrivate *priv = TEST_FILE (gobject)->priv;
|
||||||
|
|
||||||
|
g_free (priv->path);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (test_file_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_class_init (TestFileClass *klass)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = test_file_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (TestFilePrivate));
|
||||||
|
|
||||||
|
test_file_properties[PROP_PATH] =
|
||||||
|
g_string_property_new ("path",
|
||||||
|
G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
|
||||||
|
G_STRUCT_OFFSET (TestFilePrivate, path),
|
||||||
|
(GPropertyStringSet) test_file_set_path,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
test_file_properties[PROP_SIZE] =
|
||||||
|
g_string_property_new ("size", G_PROPERTY_READABLE,
|
||||||
|
G_STRUCT_OFFSET (TestFilePrivate, size),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
g_object_class_install_properties (G_OBJECT_CLASS (klass),
|
||||||
|
G_N_ELEMENTS (test_file_properties),
|
||||||
|
test_file_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_init (TestFile *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
|
TEST_TYPE_FILE,
|
||||||
|
TestFilePrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
TestFile *f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
f = g_object_new (TEST_TYPE_FILE, NULL);
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
test_file_set_path (f, argv[i]);
|
||||||
|
|
||||||
|
g_print ("File: %s, size: %" G_GINT64_FORMAT "\n",
|
||||||
|
test_file_get_path (f),
|
||||||
|
test_file_get_size (f));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (f);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
312
gobject/tests/gproperty-example-derived.c
Normal file
312
gobject/tests/gproperty-example-derived.c
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
/* Test::File {{{ */
|
||||||
|
|
||||||
|
#define TEST_TYPE_FILE (test_file_get_type ())
|
||||||
|
#define TEST_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_FILE, TestFile))
|
||||||
|
#define TEST_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_FILE))
|
||||||
|
|
||||||
|
typedef struct _TestFile TestFile;
|
||||||
|
typedef struct _TestFilePrivate TestFilePrivate;
|
||||||
|
typedef struct _TestFileClass TestFileClass;
|
||||||
|
|
||||||
|
struct _TestFile
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
TestFilePrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestFileClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestFilePrivate
|
||||||
|
{
|
||||||
|
gchar *path;
|
||||||
|
gchar *extension;
|
||||||
|
|
||||||
|
gint64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType test_file_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (TestFile, test_file, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
enum { PROP_FILE_0, PROP_PATH, PROP_SIZE, PROP_EXTENSION, LAST_FILE_PROP };
|
||||||
|
|
||||||
|
static GParamSpec *test_file_properties[LAST_FILE_PROP] = { NULL, };
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET_SET (TestFile, test_file, const gchar *, path)
|
||||||
|
|
||||||
|
G_DEFINE_PROPERTY_GET (TestFile, test_file, const gchar *, path)
|
||||||
|
|
||||||
|
void
|
||||||
|
test_file_set_path (TestFile *self,
|
||||||
|
const gchar *value)
|
||||||
|
{
|
||||||
|
GStatBuf s_buf;
|
||||||
|
|
||||||
|
g_return_if_fail (TEST_IS_FILE (self));
|
||||||
|
g_return_if_fail (value != NULL && *value != '\0');
|
||||||
|
|
||||||
|
if (g_strcmp0 (value, self->priv->path) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (g_stat (value, &s_buf) == -1)
|
||||||
|
{
|
||||||
|
int saved_errno = errno;
|
||||||
|
|
||||||
|
g_warning ("Unable to access the path: %s", g_strerror (saved_errno));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->priv->size = (gint64) s_buf.st_size;
|
||||||
|
|
||||||
|
g_free (self->priv->path);
|
||||||
|
self->priv->path = g_strdup (value);
|
||||||
|
|
||||||
|
self->priv->extension = strrchr (self->priv->path, '.');
|
||||||
|
|
||||||
|
if (self->priv->extension != NULL &&
|
||||||
|
strlen (self->priv->extension) != 0)
|
||||||
|
{
|
||||||
|
self->priv->extension += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self->priv->extension = NULL;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), test_file_properties[PROP_PATH]);
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), test_file_properties[PROP_SIZE]);
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), test_file_properties[PROP_EXTENSION]);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET (TestFile, test_file, const gchar *, extension)
|
||||||
|
G_DEFINE_PROPERTY_GET (TestFile, test_file, const gchar *, extension)
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET (TestFile, test_file, gint64, size)
|
||||||
|
G_DEFINE_PROPERTY_GET (TestFile, test_file, gint64, size)
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
TestFilePrivate *priv = TEST_FILE (gobject)->priv;
|
||||||
|
|
||||||
|
g_free (priv->path);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (test_file_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_class_init (TestFileClass *klass)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = test_file_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (TestFilePrivate));
|
||||||
|
|
||||||
|
test_file_properties[PROP_PATH] =
|
||||||
|
g_string_property_new ("path", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestFilePrivate, path),
|
||||||
|
(GPropertyStringSet) test_file_set_path,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
test_file_properties[PROP_EXTENSION] =
|
||||||
|
g_string_property_new ("extension", G_PROPERTY_READABLE,
|
||||||
|
G_STRUCT_OFFSET (TestFilePrivate, extension),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_file_properties[PROP_SIZE] =
|
||||||
|
g_string_property_new ("size", G_PROPERTY_READABLE,
|
||||||
|
G_STRUCT_OFFSET (TestFilePrivate, size),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
g_object_class_install_properties (G_OBJECT_CLASS (klass),
|
||||||
|
G_N_ELEMENTS (test_file_properties),
|
||||||
|
test_file_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_init (TestFile *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
|
TEST_TYPE_FILE,
|
||||||
|
TestFilePrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* Test::File::Mp3 {{{ */
|
||||||
|
|
||||||
|
#define TEST_TYPE_FILE_MP3 (test_file_mp3_get_type ())
|
||||||
|
#define TEST_FILE_MP3(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_FILE_MP3, TestFileMp3))
|
||||||
|
#define TEST_IS_FILE_MP3(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_FILE_MP3))
|
||||||
|
|
||||||
|
typedef struct _TestFileMp3 TestFileMp3;
|
||||||
|
typedef struct _TestFileMp3Private TestFileMp3Private;
|
||||||
|
typedef struct _TestFileMp3Class TestFileMp3Class;
|
||||||
|
|
||||||
|
struct _TestFileMp3
|
||||||
|
{
|
||||||
|
TestFile parent_instance;
|
||||||
|
|
||||||
|
TestFileMp3Private *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestFileMp3Class
|
||||||
|
{
|
||||||
|
TestFileClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestFileMp3Private
|
||||||
|
{
|
||||||
|
gchar *artist;
|
||||||
|
gchar *title;
|
||||||
|
gchar *album;
|
||||||
|
|
||||||
|
gint64 duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType test_file_mp3_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (TestFileMp3, test_file_mp3, TEST_TYPE_FILE)
|
||||||
|
|
||||||
|
enum { PROP_MP3_0, PROP_ARTIST, PROP_TITLE, PROP_ALBUM, PROP_DURATION, LAST_MP3_PROP };
|
||||||
|
|
||||||
|
static GParamSpec *test_file_mp3_properties[LAST_MP3_PROP] = { NULL, };
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, const gchar *, artist) /* for -Wmissing-prototypes */
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, const gchar *, artist)
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, const gchar *, title) /* for -Wmissing-prototypes */
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, const gchar *, title)
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, const gchar *, album) /* for -Wmissing-prototypes */
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, const gchar *, album)
|
||||||
|
|
||||||
|
G_DECLARE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, gint64, duration) /* for -Wmissing-prototypes */
|
||||||
|
G_DEFINE_PROPERTY_GET_SET (TestFileMp3, test_file_mp3, gint64, duration)
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_mp3_play (TestFileMp3 *file)
|
||||||
|
{
|
||||||
|
g_return_if_fail (TEST_IS_FILE_MP3 (file));
|
||||||
|
|
||||||
|
g_print ("Playing...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_mp3_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
TestFileMp3Private *priv = TEST_FILE_MP3 (gobject)->priv;
|
||||||
|
|
||||||
|
g_free (priv->artist);
|
||||||
|
g_free (priv->album);
|
||||||
|
g_free (priv->title);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (test_file_mp3_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_mp3_class_init (TestFileMp3Class *klass)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = test_file_mp3_finalize;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (TestFileMp3Private));
|
||||||
|
|
||||||
|
test_file_mp3_properties[PROP_ALBUM] =
|
||||||
|
g_string_property_new ("album",
|
||||||
|
G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
|
||||||
|
G_STRUCT_OFFSET (TestFileMp3Private, album),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_default (G_PROPERTY (test_file_mp3_properties[PROP_ALBUM]),
|
||||||
|
klass,
|
||||||
|
"Unknown Album");
|
||||||
|
|
||||||
|
test_file_mp3_properties[PROP_ARTIST] =
|
||||||
|
g_string_property_new ("artist",
|
||||||
|
G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
|
||||||
|
G_STRUCT_OFFSET (TestFileMp3Private, artist),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_default (G_PROPERTY (test_file_mp3_properties[PROP_ARTIST]),
|
||||||
|
klass,
|
||||||
|
"Unknown Author");
|
||||||
|
|
||||||
|
test_file_mp3_properties[PROP_TITLE] =
|
||||||
|
g_string_property_new ("title",
|
||||||
|
G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
|
||||||
|
G_STRUCT_OFFSET (TestFileMp3Private, title),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_default (G_PROPERTY (test_file_mp3_properties[PROP_TITLE]),
|
||||||
|
klass,
|
||||||
|
"Unknown Track");
|
||||||
|
|
||||||
|
test_file_mp3_properties[PROP_DURATION] =
|
||||||
|
g_int64_property_new ("duration", G_PROPERTY_READABLE,
|
||||||
|
G_STRUCT_OFFSET (TestFileMp3Private, duration),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
g_object_class_install_properties (G_OBJECT_CLASS (klass),
|
||||||
|
G_N_ELEMENTS (test_file_mp3_properties),
|
||||||
|
test_file_mp3_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_file_mp3_init (TestFileMp3 *self)
|
||||||
|
{
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
|
TEST_TYPE_FILE_MP3,
|
||||||
|
TestFileMp3Private);
|
||||||
|
|
||||||
|
g_property_get_default (G_PROPERTY (test_file_mp3_properties[PROP_ARTIST]),
|
||||||
|
self,
|
||||||
|
&(self->priv->artist));
|
||||||
|
g_property_get_default (G_PROPERTY (test_file_mp3_properties[PROP_ALBUM]),
|
||||||
|
self,
|
||||||
|
&(self->priv->album));
|
||||||
|
g_property_get_default (G_PROPERTY (test_file_mp3_properties[PROP_TITLE]),
|
||||||
|
self,
|
||||||
|
&(self->priv->title));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* main {{{ */
|
||||||
|
int
|
||||||
|
main (int argc,
|
||||||
|
char *argv[])
|
||||||
|
{
|
||||||
|
TestFile *f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
f = g_object_new (TEST_TYPE_FILE_MP3, NULL);
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
test_file_set_path (f, argv[i]);
|
||||||
|
|
||||||
|
if (g_strcmp0 (test_file_get_extension (f), "mp3") != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_print ("File: %s, size: %" G_GINT64_FORMAT "\n",
|
||||||
|
test_file_get_path (f),
|
||||||
|
test_file_get_size (f));
|
||||||
|
g_print (" Track: %s - %s\n",
|
||||||
|
test_file_mp3_get_artist (TEST_FILE_MP3 (f)),
|
||||||
|
test_file_mp3_get_title (TEST_FILE_MP3 (f)));
|
||||||
|
|
||||||
|
test_file_mp3_play (TEST_FILE_MP3 (f));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (f);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
/* }}} */
|
@ -424,6 +424,333 @@ complex_object_init (ComplexObject *complex_object)
|
|||||||
complex_object->val2 = 43;
|
complex_object->val2 = 43;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
* ParamspecObject is an object using GParamSpec for properties *
|
||||||
|
****************************************************************/
|
||||||
|
|
||||||
|
#define PARAMSPEC_TYPE_OBJECT (paramspec_object_get_type ())
|
||||||
|
typedef struct _ParamspecObject ParamspecObject;
|
||||||
|
typedef struct _ParamspecObjectClass ParamspecObjectClass;
|
||||||
|
typedef struct _ParamspecObjectPrivate ParamspecObjectPrivate;
|
||||||
|
|
||||||
|
struct _ParamspecObject
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
ParamspecObjectPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ParamspecObjectClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType paramspec_object_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (ParamspecObject, paramspec_object, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define PARAMSPEC_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PARAMSPEC_TYPE_OBJECT, ParamspecObject))
|
||||||
|
|
||||||
|
struct _ParamspecObjectPrivate
|
||||||
|
{
|
||||||
|
int foo;
|
||||||
|
gchar *bar;
|
||||||
|
float baz;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_PSPEC_0,
|
||||||
|
PROP_PSPEC_FOO,
|
||||||
|
PROP_PSPEC_BAR,
|
||||||
|
PROP_PSPEC_BAZ,
|
||||||
|
PROP_PSPEC_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *pspec_props[PROP_PSPEC_LAST] = { NULL, };
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
ParamspecObjectPrivate *priv = PARAMSPEC_OBJECT (object)->priv;
|
||||||
|
|
||||||
|
g_free (priv->bar);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (paramspec_object_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_set_foo (ParamspecObject *object,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
if (object->priv->foo == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
object->priv->foo = value;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_FOO]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
paramspec_object_get_foo (ParamspecObject *object)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (object, paramspec_object_get_type ()), 0);
|
||||||
|
|
||||||
|
return object->priv->foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_set_bar (ParamspecObject *object,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (object->priv->bar, value) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free (object->priv->bar);
|
||||||
|
object->priv->bar = g_strdup (value);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_BAR]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_set_baz (ParamspecObject *object,
|
||||||
|
float value)
|
||||||
|
{
|
||||||
|
if (object->priv->baz == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
object->priv->baz = value;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (object), pspec_props[PROP_PSPEC_BAZ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
paramspec_object_get_baz (ParamspecObject *object)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (object, paramspec_object_get_type ()), 0.0);
|
||||||
|
|
||||||
|
return object->priv->baz;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_PSPEC_FOO:
|
||||||
|
paramspec_object_set_foo (PARAMSPEC_OBJECT (object), g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
case PROP_PSPEC_BAR:
|
||||||
|
paramspec_object_set_bar (PARAMSPEC_OBJECT (object), g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_PSPEC_BAZ:
|
||||||
|
paramspec_object_set_baz (PARAMSPEC_OBJECT (object), g_value_get_float (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_PSPEC_FOO:
|
||||||
|
g_value_set_int (value, PARAMSPEC_OBJECT (object)->priv->foo);
|
||||||
|
break;
|
||||||
|
case PROP_PSPEC_BAR:
|
||||||
|
g_value_set_string (value, PARAMSPEC_OBJECT (object)->priv->bar);
|
||||||
|
break;
|
||||||
|
case PROP_PSPEC_BAZ:
|
||||||
|
g_value_set_float (value, PARAMSPEC_OBJECT (object)->priv->baz);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_class_init (ParamspecObjectClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||||
|
|
||||||
|
g_type_class_add_private (class, sizeof (ParamspecObjectPrivate));
|
||||||
|
|
||||||
|
object_class->finalize = paramspec_object_finalize;
|
||||||
|
object_class->set_property = paramspec_object_set_property;
|
||||||
|
object_class->get_property = paramspec_object_get_property;
|
||||||
|
|
||||||
|
pspec_props[PROP_PSPEC_FOO] =
|
||||||
|
g_param_spec_int ("foo",
|
||||||
|
NULL, NULL,
|
||||||
|
-100, 100, 50,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||||
|
pspec_props[PROP_PSPEC_BAR] =
|
||||||
|
g_param_spec_string ("bar",
|
||||||
|
NULL, NULL,
|
||||||
|
"Hello",
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||||
|
pspec_props[PROP_PSPEC_BAZ] =
|
||||||
|
g_param_spec_float ("baz",
|
||||||
|
NULL, NULL,
|
||||||
|
0.0f, G_MAXFLOAT, 0.0f,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, PROP_PSPEC_LAST, pspec_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
paramspec_object_init (ParamspecObject *self)
|
||||||
|
{
|
||||||
|
self->priv = g_type_instance_get_private ((GTypeInstance *) self, PARAMSPEC_TYPE_OBJECT);
|
||||||
|
|
||||||
|
self->priv->foo = 50;
|
||||||
|
self->priv->bar = g_strdup ("Hello");
|
||||||
|
self->priv->baz = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
* PropertyObject is an object using GProperty for properties *
|
||||||
|
**************************************************************/
|
||||||
|
|
||||||
|
#define PROPERTY_TYPE_OBJECT (property_object_get_type ())
|
||||||
|
typedef struct _PropertyObject PropertyObject;
|
||||||
|
typedef struct _PropertyObjectClass PropertyObjectClass;
|
||||||
|
typedef struct _PropertyObjectPrivate PropertyObjectPrivate;
|
||||||
|
|
||||||
|
struct _PropertyObject
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
PropertyObjectPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _PropertyObjectClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType property_object_get_type (void); /* for -Wmissing-prototypes */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (PropertyObject, property_object, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define PROPERTY_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PROPERTY_TYPE_OBJECT, PropertyObject))
|
||||||
|
|
||||||
|
struct _PropertyObjectPrivate
|
||||||
|
{
|
||||||
|
int foo;
|
||||||
|
gchar *bar;
|
||||||
|
float baz;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_PROPERTY_0,
|
||||||
|
PROP_PROPERTY_FOO,
|
||||||
|
PROP_PROPERTY_BAR,
|
||||||
|
PROP_PROPERTY_BAZ,
|
||||||
|
PROP_PROPERTY_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *property_props[PROP_PROPERTY_LAST] = { NULL, };
|
||||||
|
|
||||||
|
static void
|
||||||
|
property_object_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
PropertyObjectPrivate *priv = PROPERTY_OBJECT (object)->priv;
|
||||||
|
|
||||||
|
g_free (priv->bar);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (property_object_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
property_object_class_init (PropertyObjectClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||||
|
|
||||||
|
g_type_class_add_private (class, sizeof (PropertyObjectPrivate));
|
||||||
|
|
||||||
|
object_class->finalize = property_object_finalize;
|
||||||
|
|
||||||
|
property_props[PROP_PROPERTY_FOO] =
|
||||||
|
g_int_property_new ("foo", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (PropertyObjectPrivate, foo),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_range ((GProperty *) property_props[PROP_PROPERTY_FOO], -100, 100);
|
||||||
|
g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_FOO], 50);
|
||||||
|
|
||||||
|
property_props[PROP_PROPERTY_BAR] =
|
||||||
|
g_string_property_new ("bar", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (PropertyObjectPrivate, bar),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_BAR], "Hello");
|
||||||
|
|
||||||
|
property_props[PROP_PROPERTY_BAZ] =
|
||||||
|
g_float_property_new ("baz", G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (PropertyObjectPrivate, baz),
|
||||||
|
NULL, NULL);
|
||||||
|
g_property_set_range ((GProperty *) property_props[PROP_PROPERTY_BAZ], 0.0f, G_MAXFLOAT);
|
||||||
|
g_property_set_default ((GProperty *) property_props[PROP_PROPERTY_BAZ], 0.0f);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, PROP_PROPERTY_LAST, property_props);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
property_object_init (PropertyObject *self)
|
||||||
|
{
|
||||||
|
self->priv = g_type_instance_get_private ((GTypeInstance *) self, PROPERTY_TYPE_OBJECT);
|
||||||
|
|
||||||
|
g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_FOO],
|
||||||
|
self,
|
||||||
|
&(self->priv->foo));
|
||||||
|
g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_BAR],
|
||||||
|
self,
|
||||||
|
&(self->priv->bar));
|
||||||
|
g_property_get_default ((GProperty *) property_props[PROP_PROPERTY_BAZ],
|
||||||
|
self,
|
||||||
|
&(self->priv->baz));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
property_object_set_foo (PropertyObject *self, int value)
|
||||||
|
{
|
||||||
|
g_property_set (((GProperty *) property_props[PROP_PROPERTY_FOO]), self, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
property_object_get_foo (PropertyObject *self)
|
||||||
|
{
|
||||||
|
gint value;
|
||||||
|
|
||||||
|
g_property_get (((GProperty *) property_props[PROP_PROPERTY_FOO]), self, &value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
property_object_set_baz (PropertyObject *self, float value)
|
||||||
|
{
|
||||||
|
g_property_set (((GProperty *) property_props[PROP_PROPERTY_BAZ]), self, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
property_object_get_baz (PropertyObject *self)
|
||||||
|
{
|
||||||
|
float value;
|
||||||
|
|
||||||
|
g_property_get (((GProperty *) property_props[PROP_PROPERTY_BAZ]), self, &value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Test object construction performance
|
* Test object construction performance
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
@ -508,6 +835,186 @@ test_construction_print_result (PerformanceTest *test,
|
|||||||
data->n_objects / time);
|
data->n_objects / time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
* Test property accessors using GParamSpec
|
||||||
|
*************************************************************/
|
||||||
|
|
||||||
|
#define NUM_ACCESSES_PER_ROUND 10000
|
||||||
|
|
||||||
|
struct PropertyTest {
|
||||||
|
gpointer object;
|
||||||
|
int n_accesses;
|
||||||
|
};
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
test_property_setup (PerformanceTest *test)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data;
|
||||||
|
GType gtype;
|
||||||
|
|
||||||
|
gtype = ((GType (*)())test->extra_data)();
|
||||||
|
|
||||||
|
data = g_new0 (struct PropertyTest, 1);
|
||||||
|
data->object = g_object_new (gtype, NULL);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_init (PerformanceTest *test,
|
||||||
|
gpointer _data,
|
||||||
|
double factor)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
|
||||||
|
data->n_accesses = factor * NUM_ACCESSES_PER_ROUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_paramspec_direct_set_run (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
int n_accesses, i;
|
||||||
|
|
||||||
|
n_accesses = data->n_accesses;
|
||||||
|
for (i = 0; i < n_accesses; i++)
|
||||||
|
{
|
||||||
|
gint foo = i % 16;
|
||||||
|
gfloat baz = foo * 3.14f;
|
||||||
|
|
||||||
|
paramspec_object_set_foo (data->object, foo);
|
||||||
|
paramspec_object_set_baz (data->object, baz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_paramspec_direct_get_run (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
int n_accesses, i;
|
||||||
|
|
||||||
|
n_accesses = data->n_accesses;
|
||||||
|
for (i = 0; i < n_accesses; i++)
|
||||||
|
{
|
||||||
|
gint foo;
|
||||||
|
gfloat baz;
|
||||||
|
|
||||||
|
foo = paramspec_object_get_foo (data->object);
|
||||||
|
baz = paramspec_object_get_baz (data->object);
|
||||||
|
|
||||||
|
g_assert_cmpfloat (baz, ==, 0);
|
||||||
|
g_assert_cmpint (foo, ==, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_paramspec_object_run (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
int n_accesses, i;
|
||||||
|
|
||||||
|
n_accesses = data->n_accesses;
|
||||||
|
for (i = 0; i < n_accesses; i++)
|
||||||
|
{
|
||||||
|
gint foo = i % 16;
|
||||||
|
gfloat baz = foo * 3.14f;
|
||||||
|
|
||||||
|
g_object_set (data->object,
|
||||||
|
"foo", foo,
|
||||||
|
"baz", baz,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_direct_set_run (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
int n_accesses, i;
|
||||||
|
|
||||||
|
n_accesses = data->n_accesses;
|
||||||
|
for (i = 0; i < n_accesses; i++)
|
||||||
|
{
|
||||||
|
gint foo = i % 16;
|
||||||
|
gfloat baz = foo * 3.14f;
|
||||||
|
|
||||||
|
property_object_set_foo (data->object, foo);
|
||||||
|
property_object_set_baz (data->object, baz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_direct_get_run (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
int n_accesses, i;
|
||||||
|
|
||||||
|
n_accesses = data->n_accesses;
|
||||||
|
for (i = 0; i < n_accesses; i++)
|
||||||
|
{
|
||||||
|
gint foo;
|
||||||
|
gfloat baz;
|
||||||
|
|
||||||
|
foo = property_object_get_foo (data->object);
|
||||||
|
baz = property_object_get_baz (data->object);
|
||||||
|
|
||||||
|
g_assert_cmpfloat (baz, ==, 0);
|
||||||
|
g_assert_cmpint (foo, ==, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_object_run (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
int n_accesses, i;
|
||||||
|
|
||||||
|
n_accesses = data->n_accesses;
|
||||||
|
for (i = 0; i < n_accesses; i++)
|
||||||
|
{
|
||||||
|
gint foo = i % 16;
|
||||||
|
gfloat baz = foo * 3.14f;
|
||||||
|
|
||||||
|
g_object_set (data->object,
|
||||||
|
"foo", foo,
|
||||||
|
"baz", baz,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_finish (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_print_result (PerformanceTest *test,
|
||||||
|
gpointer _data,
|
||||||
|
gdouble time)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
g_print ("Number of accesses per second: %.0f\n",
|
||||||
|
data->n_accesses / time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_property_teardown (PerformanceTest *test,
|
||||||
|
gpointer _data)
|
||||||
|
{
|
||||||
|
struct PropertyTest *data = _data;
|
||||||
|
|
||||||
|
g_object_unref (data->object);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
* Test runtime type check performance
|
* Test runtime type check performance
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
@ -781,6 +1288,66 @@ static PerformanceTest tests[] = {
|
|||||||
test_construction_teardown,
|
test_construction_teardown,
|
||||||
test_construction_print_result
|
test_construction_print_result
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"gparamspec-direct-get",
|
||||||
|
paramspec_object_get_type,
|
||||||
|
test_property_setup,
|
||||||
|
test_property_init,
|
||||||
|
test_paramspec_direct_get_run,
|
||||||
|
test_property_finish,
|
||||||
|
test_property_teardown,
|
||||||
|
test_property_print_result
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gproperty-direct-get",
|
||||||
|
property_object_get_type,
|
||||||
|
test_property_setup,
|
||||||
|
test_property_init,
|
||||||
|
test_property_direct_get_run,
|
||||||
|
test_property_finish,
|
||||||
|
test_property_teardown,
|
||||||
|
test_property_print_result
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gparamspec-direct-set",
|
||||||
|
paramspec_object_get_type,
|
||||||
|
test_property_setup,
|
||||||
|
test_property_init,
|
||||||
|
test_paramspec_direct_set_run,
|
||||||
|
test_property_finish,
|
||||||
|
test_property_teardown,
|
||||||
|
test_property_print_result
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gproperty-direct-set",
|
||||||
|
property_object_get_type,
|
||||||
|
test_property_setup,
|
||||||
|
test_property_init,
|
||||||
|
test_property_direct_set_run,
|
||||||
|
test_property_finish,
|
||||||
|
test_property_teardown,
|
||||||
|
test_property_print_result
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gparamspec-gobject-access",
|
||||||
|
paramspec_object_get_type,
|
||||||
|
test_property_setup,
|
||||||
|
test_property_init,
|
||||||
|
test_paramspec_object_run,
|
||||||
|
test_property_finish,
|
||||||
|
test_property_teardown,
|
||||||
|
test_property_print_result
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"gproperty-gobject-access",
|
||||||
|
property_object_get_type,
|
||||||
|
test_property_setup,
|
||||||
|
test_property_init,
|
||||||
|
test_property_object_run,
|
||||||
|
test_property_finish,
|
||||||
|
test_property_teardown,
|
||||||
|
test_property_print_result
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type-check",
|
"type-check",
|
||||||
NULL,
|
NULL,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user