mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +01:00
gobject: Add GProperty
Dealing with GParamSpec is tedious and less efficient than necessary. GParamSpec is a data type meant to be used to validate GValue, and only incidentally provides us with the facilities to implement properties on GObject. GObject itself requires us to provide accessors functions and then call them from within a huge switch() inside two virtual functions. 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 C fundamental 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 enforced at compile time through the C type system, and at run time through the GType system. GProperty will try *very* hard to avoid boxing and unboxing fundamental type values into GValues. 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
c44fdf47f6
commit
959940f896
@ -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>
|
||||||
|
@ -69,6 +69,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 \
|
||||||
@ -98,6 +99,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 \
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "gsignal.h"
|
#include "gsignal.h"
|
||||||
#include "gparamspecs.h"
|
#include "gparamspecs.h"
|
||||||
#include "gvaluetypes.h"
|
#include "gvaluetypes.h"
|
||||||
|
#include "gproperty.h"
|
||||||
#include "gobject_trace.h"
|
#include "gobject_trace.h"
|
||||||
#include "gconstructor.h"
|
#include "gconstructor.h"
|
||||||
|
|
||||||
@ -561,6 +562,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 ((GProperty *) 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_append (class->construct_properties, pspec);
|
class->construct_properties = g_slist_append (class->construct_properties, pspec);
|
||||||
|
|
||||||
@ -668,9 +672,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) != 0)
|
||||||
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) != 0)
|
||||||
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)
|
||||||
@ -681,6 +685,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 ((GProperty *) pspec, oclass, G_OBJECT_CLASS_TYPE (oclass));
|
||||||
|
|
||||||
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_append (oclass->construct_properties, pspec);
|
oclass->construct_properties = g_slist_append (oclass->construct_properties, pspec);
|
||||||
|
|
||||||
@ -1297,7 +1304,10 @@ object_get_property (GObject *object,
|
|||||||
if (redirect)
|
if (redirect)
|
||||||
pspec = redirect;
|
pspec = redirect;
|
||||||
|
|
||||||
class->get_property (object, param_id, value, pspec);
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
g_property_get_value ((GProperty *) pspec, object, value);
|
||||||
|
else
|
||||||
|
class->get_property (object, param_id, value, pspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -1358,15 +1368,27 @@ object_set_property (GObject *object,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GParamSpec *notify_pspec;
|
if (G_IS_PROPERTY (pspec))
|
||||||
|
{
|
||||||
|
/* if the setter did not emit change the property then we don't
|
||||||
|
* need to notify either; if it did, the notify_queue_add() will
|
||||||
|
* just be a no-op
|
||||||
|
*/
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4605
gobject/gproperty.c
Normal file
4605
gobject/gproperty.c
Normal file
File diff suppressed because it is too large
Load Diff
413
gobject/gproperty.h
Normal file
413
gobject/gproperty.h
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/* gproperty.h: Property definitions for GObject
|
||||||
|
*
|
||||||
|
* Copyright © 2013 Emmanuele Bassi
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __G_PROPERTY_H__
|
||||||
|
#define __G_PROPERTY_H__
|
||||||
|
|
||||||
|
#if !defined (__GLIB_GOBJECT_H_INSIDE__) && !defined (GOBJECT_COMPILATION)
|
||||||
|
#error "Only <glib-object.h> can be included directly."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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.38
|
||||||
|
*/
|
||||||
|
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_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
|
||||||
|
* @G_PROPERTY_DEPRECATED: Whether the property is deprecated and should
|
||||||
|
* not be accessed in newly written code.
|
||||||
|
* @G_PROPERTY_CONSTRUCT_ONLY: Whether the property is meant to be set
|
||||||
|
* only during construction. Implies %G_PROPERTY_WRITABLE.
|
||||||
|
*
|
||||||
|
* Flags for properties declared using #GProperty and relative macros.
|
||||||
|
*
|
||||||
|
* This enumeration might be extended at later date.
|
||||||
|
*
|
||||||
|
* Since: 2.38
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
G_PROPERTY_READABLE = 1 << 0,
|
||||||
|
G_PROPERTY_WRITABLE = 1 << 1,
|
||||||
|
G_PROPERTY_READWRITE = (G_PROPERTY_READABLE | G_PROPERTY_WRITABLE),
|
||||||
|
|
||||||
|
G_PROPERTY_COPY_SET = 1 << 2,
|
||||||
|
G_PROPERTY_COPY_GET = 1 << 3,
|
||||||
|
G_PROPERTY_COPY = (G_PROPERTY_COPY_SET | G_PROPERTY_COPY_GET),
|
||||||
|
|
||||||
|
G_PROPERTY_DEPRECATED = 1 << 4,
|
||||||
|
G_PROPERTY_CONSTRUCT_ONLY = 1 << 5
|
||||||
|
} GPropertyFlags;
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GType g_property_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
/* general purpose API */
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
const gchar * g_property_canonicalize_name (const char *name);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GType g_property_get_value_type (GProperty *property);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_is_writable (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_is_readable (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_is_deprecated (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_is_copy_set (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_is_copy_get (GProperty *property);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_is_construct_only (GProperty *property);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
void g_property_set_range_values (GProperty *property,
|
||||||
|
const GValue *min_value,
|
||||||
|
const GValue *max_value);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_get_range_values (GProperty *property,
|
||||||
|
GValue *min_value,
|
||||||
|
GValue *max_value);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
void g_property_set_range (GProperty *property,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_get_range (GProperty *property,
|
||||||
|
...);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
void g_property_set_prerequisite (GProperty *property,
|
||||||
|
...);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_validate (GProperty *property,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_validate_value (GProperty *property,
|
||||||
|
GValue *value);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_set_value (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
const GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
void g_property_get_value (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GValue *value);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_set (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
...);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
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.38
|
||||||
|
*/
|
||||||
|
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_38
|
||||||
|
gboolean g_property_set_va (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GPropertyCollectFlags flags,
|
||||||
|
va_list *app);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
gboolean g_property_get_va (GProperty *property,
|
||||||
|
gpointer gobject,
|
||||||
|
GPropertyCollectFlags flags,
|
||||||
|
va_list *app);
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
gint value);
|
||||||
|
typedef gint (* GPropertyEnumGet) (gpointer gobject);
|
||||||
|
|
||||||
|
typedef gboolean (* GPropertyFlagsSet) (gpointer gobject,
|
||||||
|
guint value);
|
||||||
|
typedef guint (* 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_38
|
||||||
|
GParamSpec * g_boolean_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyBooleanSet setter,
|
||||||
|
GPropertyBooleanGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_int_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyIntSet setter,
|
||||||
|
GPropertyIntGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_int8_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt8Set setter,
|
||||||
|
GPropertyInt8Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_int16_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt16Set setter,
|
||||||
|
GPropertyInt16Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_int32_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt32Set setter,
|
||||||
|
GPropertyInt32Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_int64_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyInt64Set setter,
|
||||||
|
GPropertyInt64Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_long_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyLongSet setter,
|
||||||
|
GPropertyLongGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_uint_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUIntSet setter,
|
||||||
|
GPropertyUIntGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_uint8_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt8Set setter,
|
||||||
|
GPropertyUInt8Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_uint16_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt16Set setter,
|
||||||
|
GPropertyUInt16Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_uint32_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt32Set setter,
|
||||||
|
GPropertyUInt32Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_uint64_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyUInt64Set setter,
|
||||||
|
GPropertyUInt64Get getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
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_38
|
||||||
|
GParamSpec * g_enum_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyEnumSet setter,
|
||||||
|
GPropertyEnumGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_flags_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyFlagsSet setter,
|
||||||
|
GPropertyFlagsGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_float_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyFloatSet setter,
|
||||||
|
GPropertyFloatGet getter);
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_double_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyDoubleSet setter,
|
||||||
|
GPropertyDoubleGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_string_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyStringSet setter,
|
||||||
|
GPropertyStringGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_boxed_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyBoxedSet setter,
|
||||||
|
GPropertyBoxedGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_object_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyObjectSet setter,
|
||||||
|
GPropertyObjectGet getter);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_38
|
||||||
|
GParamSpec * g_pointer_property_new (const gchar *name,
|
||||||
|
GPropertyFlags flags,
|
||||||
|
gssize field_offset,
|
||||||
|
GPropertyPointerSet setter,
|
||||||
|
GPropertyPointerGet getter);
|
||||||
|
|
||||||
|
|
||||||
|
/* private API */
|
||||||
|
void _g_property_set_installed (GProperty *property,
|
||||||
|
gpointer g_class,
|
||||||
|
GType class_gtype);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __G_PROPERTY_H__ */
|
1
gobject/tests/.gitignore
vendored
1
gobject/tests/.gitignore
vendored
@ -12,3 +12,4 @@ threadtests
|
|||||||
valuearray
|
valuearray
|
||||||
private
|
private
|
||||||
marshalers.[ch]
|
marshalers.[ch]
|
||||||
|
property
|
||||||
|
@ -20,6 +20,7 @@ test_programs = \
|
|||||||
valuearray \
|
valuearray \
|
||||||
type \
|
type \
|
||||||
private \
|
private \
|
||||||
|
property \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
274
gobject/tests/property.c
Normal file
274
gobject/tests/property.c
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
typedef struct _TestObject TestObject;
|
||||||
|
typedef struct _TestObjectPrivate TestObjectPrivate;
|
||||||
|
typedef struct _TestObjectClass TestObjectClass;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TEST_ENUM_UNSET,
|
||||||
|
TEST_ENUM_ONE,
|
||||||
|
TEST_ENUM_TWO,
|
||||||
|
TEST_ENUM_THREE
|
||||||
|
} TestEnum;
|
||||||
|
|
||||||
|
struct _TestObject
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestObjectClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TestObjectPrivate
|
||||||
|
{
|
||||||
|
int integer_val;
|
||||||
|
|
||||||
|
double double_val;
|
||||||
|
|
||||||
|
char *str_val;
|
||||||
|
|
||||||
|
gboolean bool_val;
|
||||||
|
|
||||||
|
TestEnum enum_val;
|
||||||
|
guint enum_val_set : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType test_enum_get_type (void);
|
||||||
|
GType test_object_get_type (void);
|
||||||
|
|
||||||
|
GType
|
||||||
|
test_enum_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_UNSET, "TEST_ENUM_UNSET", "unset" },
|
||||||
|
{ TEST_ENUM_ONE, "TEST_ENUM_ONE", "one" },
|
||||||
|
{ TEST_ENUM_TWO, "TEST_ENUM_TWO", "two" },
|
||||||
|
{ TEST_ENUM_THREE, "TEST_ENUM_THREE", "three" },
|
||||||
|
{ 0, NULL, NULL }
|
||||||
|
};
|
||||||
|
GType g_define_type_id =
|
||||||
|
g_enum_register_static (g_intern_static_string ("TestEnum"), values);
|
||||||
|
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_define_type_id__volatile;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (TestObject, test_object, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_INTEGER_VAL,
|
||||||
|
PROP_DOUBLE_VAL,
|
||||||
|
PROP_STRING_VAL,
|
||||||
|
PROP_BOOL_VAL,
|
||||||
|
PROP_ENUM_VAL,
|
||||||
|
|
||||||
|
LAST_PROP
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *test_object_properties[LAST_PROP] = { NULL, };
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_object_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
TestObjectPrivate *priv = test_object_get_instance_private ((TestObject *) gobject);
|
||||||
|
|
||||||
|
g_free (priv->str_val);
|
||||||
|
|
||||||
|
if (priv->enum_val != TEST_ENUM_UNSET)
|
||||||
|
g_assert (priv->enum_val_set);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
test_object_set_enum_val (gpointer obj,
|
||||||
|
gint val)
|
||||||
|
{
|
||||||
|
TestObjectPrivate *priv = test_object_get_instance_private (obj);
|
||||||
|
|
||||||
|
if (priv->enum_val == val)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
priv->enum_val = val;
|
||||||
|
priv->enum_val_set = val != TEST_ENUM_UNSET;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_object_class_init (TestObjectClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = test_object_finalize;
|
||||||
|
|
||||||
|
test_object_properties[PROP_INTEGER_VAL] =
|
||||||
|
g_int_property_new ("integer-val",
|
||||||
|
G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, integer_val),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_DOUBLE_VAL] =
|
||||||
|
g_double_property_new ("double-val",
|
||||||
|
G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, double_val),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_STRING_VAL] =
|
||||||
|
g_string_property_new ("string-val",
|
||||||
|
G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, str_val),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_BOOL_VAL] =
|
||||||
|
g_boolean_property_new ("bool-val",
|
||||||
|
G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, bool_val),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
test_object_properties[PROP_ENUM_VAL] =
|
||||||
|
g_enum_property_new ("enum-val",
|
||||||
|
G_PROPERTY_READWRITE,
|
||||||
|
G_STRUCT_OFFSET (TestObjectPrivate, enum_val),
|
||||||
|
test_object_set_enum_val,
|
||||||
|
NULL);
|
||||||
|
g_property_set_prerequisite ((GProperty *) test_object_properties[PROP_ENUM_VAL],
|
||||||
|
test_enum_get_type ());
|
||||||
|
|
||||||
|
g_object_class_install_properties (gobject_class, LAST_PROP, test_object_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_object_init (TestObject *self)
|
||||||
|
{
|
||||||
|
TestObjectPrivate *priv = test_object_get_private (self);
|
||||||
|
|
||||||
|
priv->enum_val = TEST_ENUM_UNSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_notify_emission (GObject *object,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gboolean *toggle)
|
||||||
|
{
|
||||||
|
if (toggle != NULL)
|
||||||
|
*toggle = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gproperty_construct (void)
|
||||||
|
{
|
||||||
|
TestObject *obj = g_object_new (test_object_get_type (),
|
||||||
|
"integer-val", 42,
|
||||||
|
"bool-val", TRUE,
|
||||||
|
"string-val", "Hello, world",
|
||||||
|
"double-val", 3.14159,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
TestObjectPrivate *priv = test_object_get_instance_private (obj);
|
||||||
|
|
||||||
|
g_assert_cmpint (priv->integer_val, ==, 42);
|
||||||
|
g_assert (priv->bool_val);
|
||||||
|
g_assert_cmpstr (priv->str_val, ==, "Hello, world");
|
||||||
|
g_assert_cmpfloat ((float) priv->double_val, ==, 3.14159f);
|
||||||
|
|
||||||
|
g_object_unref (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gproperty_object_set (void)
|
||||||
|
{
|
||||||
|
TestObject *obj = g_object_new (test_object_get_type (), NULL);
|
||||||
|
TestObjectPrivate *priv = test_object_get_instance_private (obj);
|
||||||
|
|
||||||
|
gboolean did_emit_notify = FALSE;
|
||||||
|
|
||||||
|
g_signal_connect (obj, "notify::string-val", G_CALLBACK (check_notify_emission), &did_emit_notify);
|
||||||
|
|
||||||
|
g_object_set (obj, "string-val", "Hello!", NULL);
|
||||||
|
g_assert_cmpstr (priv->str_val, ==, "Hello!");
|
||||||
|
|
||||||
|
g_assert (did_emit_notify);
|
||||||
|
|
||||||
|
did_emit_notify = FALSE;
|
||||||
|
|
||||||
|
g_object_set (obj, "string-val", "Hello!", NULL);
|
||||||
|
g_assert_cmpstr (priv->str_val, ==, "Hello!");
|
||||||
|
|
||||||
|
g_assert (!did_emit_notify);
|
||||||
|
|
||||||
|
g_object_unref (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gproperty_object_get (void)
|
||||||
|
{
|
||||||
|
TestObject *obj = g_object_new (test_object_get_type (),
|
||||||
|
"integer-val", 42,
|
||||||
|
"string-val", "Hello!",
|
||||||
|
NULL);
|
||||||
|
int int_val = 0;
|
||||||
|
char *str_val = NULL;
|
||||||
|
|
||||||
|
g_object_get (obj, "integer-val", &int_val, NULL);
|
||||||
|
g_assert_cmpint (int_val, ==, 42);
|
||||||
|
|
||||||
|
g_object_get (obj, "string-val", &str_val, NULL);
|
||||||
|
g_assert_cmpstr (str_val, ==, "Hello!");
|
||||||
|
|
||||||
|
g_free (str_val);
|
||||||
|
g_object_unref (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gproperty_explicit_set (void)
|
||||||
|
{
|
||||||
|
TestObject *obj = g_object_new (test_object_get_type (), NULL);
|
||||||
|
gboolean did_emit_notify = FALSE;
|
||||||
|
TestEnum enum_val;
|
||||||
|
|
||||||
|
TestObjectPrivate *priv =
|
||||||
|
g_type_instance_get_private ((GTypeInstance *) obj, test_object_get_type ());
|
||||||
|
|
||||||
|
g_signal_connect (obj, "notify::enum-val", G_CALLBACK (check_notify_emission), &did_emit_notify);
|
||||||
|
|
||||||
|
g_object_set (obj, "enum-val", TEST_ENUM_THREE, NULL);
|
||||||
|
g_assert_cmpint (priv->enum_val, ==, TEST_ENUM_THREE);
|
||||||
|
g_assert (priv->enum_val_set);
|
||||||
|
|
||||||
|
g_assert (did_emit_notify);
|
||||||
|
|
||||||
|
did_emit_notify = FALSE;
|
||||||
|
g_object_set (obj, "enum-val", TEST_ENUM_THREE, NULL);
|
||||||
|
g_assert (!did_emit_notify);
|
||||||
|
|
||||||
|
g_object_get (obj, "enum-val", &enum_val, NULL);
|
||||||
|
g_assert_cmpint (enum_val, ==, TEST_ENUM_THREE);
|
||||||
|
|
||||||
|
g_object_unref (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||||
|
|
||||||
|
g_test_add_func ("/gproperty/construct", gproperty_construct);
|
||||||
|
g_test_add_func ("/gproperty/object-set", gproperty_object_set);
|
||||||
|
g_test_add_func ("/gproperty/object-get", gproperty_object_get);
|
||||||
|
g_test_add_func ("/gproperty/explicit-set", gproperty_explicit_set);
|
||||||
|
|
||||||
|
return g_test_run ();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user