mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-03 14:42:10 +01:00
Add a new GParamSpecOverride type that is a pointer to a different
Tue Oct 14 17:40:19 2003 Owen Taylor <otaylor@redhat.com> * gparamspecs.[ch]: Add a new GParamSpecOverride type that is a pointer to a different paramspec in a parent class or interface. * gparam.[ch]: Add g_paramspec_get_redirect_target() which follows GParamSpecOverride to the real property. Make g_param_spec_pool_list() hand redirections, properties on interfaces. * gobject.[ch] gobjectnotifyqueue.c: Add g_object_interface_install_property, g_object_interface_find_property, g_object_interface_list_properties(). Redirect virtually all publically exposed GParamSpec's to the redirect target if any. (->constructor is the exception.) (#105894)
This commit is contained in:
parent
4a29291187
commit
6f5794fad0
@ -1,3 +1,22 @@
|
|||||||
|
Tue Oct 14 17:40:19 2003 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
|
* gparamspecs.[ch]: Add a new GParamSpecOverride type
|
||||||
|
that is a pointer to a different paramspec in a parent
|
||||||
|
class or interface.
|
||||||
|
|
||||||
|
* gparam.[ch]: Add g_paramspec_get_redirect_target()
|
||||||
|
which follows GParamSpecOverride to the real property.
|
||||||
|
Make g_param_spec_pool_list() hand redirections,
|
||||||
|
properties on interfaces.
|
||||||
|
|
||||||
|
* gobject.[ch] gobjectnotifyqueue.c: Add
|
||||||
|
g_object_interface_install_property,
|
||||||
|
g_object_interface_find_property,
|
||||||
|
g_object_interface_list_properties(). Redirect virtually all
|
||||||
|
publically exposed GParamSpec's to the redirect target if
|
||||||
|
any. (->constructor is the exception.)
|
||||||
|
(#105894)
|
||||||
|
|
||||||
Mon Oct 20 22:06:12 2003 Matthias Clasen <maclas@gmx.de>
|
Mon Oct 20 22:06:12 2003 Matthias Clasen <maclas@gmx.de>
|
||||||
|
|
||||||
* gobject.h (struct _GObjectClass): Add /*< public >*/
|
* gobject.h (struct _GObjectClass): Add /*< public >*/
|
||||||
|
@ -97,6 +97,9 @@ static inline void object_set_property (GObject *object,
|
|||||||
const GValue *value,
|
const GValue *value,
|
||||||
GObjectNotifyQueue *nqueue);
|
GObjectNotifyQueue *nqueue);
|
||||||
|
|
||||||
|
static void object_interface_check_properties (gpointer func_data,
|
||||||
|
gpointer g_iface);
|
||||||
|
|
||||||
|
|
||||||
/* --- variables --- */
|
/* --- variables --- */
|
||||||
static GQuark quark_closure_array = 0;
|
static GQuark quark_closure_array = 0;
|
||||||
@ -256,6 +259,30 @@ g_object_do_class_init (GObjectClass *class)
|
|||||||
g_cclosure_marshal_VOID__PARAM,
|
g_cclosure_marshal_VOID__PARAM,
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
1, G_TYPE_PARAM);
|
1, G_TYPE_PARAM);
|
||||||
|
|
||||||
|
/* Install a check function that we'll use to verify that classes that
|
||||||
|
* implement an interface implement all properties for that interface
|
||||||
|
*/
|
||||||
|
g_type_add_interface_check (NULL, object_interface_check_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
install_property_internal (GType g_type,
|
||||||
|
guint property_id,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
if (g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type, FALSE))
|
||||||
|
{
|
||||||
|
g_warning ("When installing property: type `%s' already has a property named `%s'",
|
||||||
|
g_type_name (g_type),
|
||||||
|
pspec->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_param_spec_ref (pspec);
|
||||||
|
g_param_spec_sink (pspec);
|
||||||
|
PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
|
||||||
|
g_param_spec_pool_insert (pspec_pool, pspec, g_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -276,18 +303,8 @@ g_object_class_install_property (GObjectClass *class,
|
|||||||
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
|
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
|
||||||
g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
|
g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
|
||||||
|
|
||||||
if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE))
|
install_property_internal (G_OBJECT_CLASS_TYPE (class), property_id, pspec);
|
||||||
{
|
|
||||||
g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
|
|
||||||
G_OBJECT_CLASS_NAME (class),
|
|
||||||
pspec->name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_param_spec_ref (pspec);
|
|
||||||
g_param_spec_sink (pspec);
|
|
||||||
PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
|
|
||||||
g_param_spec_pool_insert (pspec_pool, pspec, 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);
|
||||||
|
|
||||||
@ -299,17 +316,110 @@ g_object_class_install_property (GObjectClass *class,
|
|||||||
class->construct_properties = g_slist_remove (class->construct_properties, pspec);
|
class->construct_properties = g_slist_remove (class->construct_properties, pspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
g_object_interface_install_property (gpointer g_iface,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GTypeInterface *iface_class = g_iface;
|
||||||
|
|
||||||
|
g_return_if_fail (G_TYPE_IS_INTERFACE (iface_class->g_type));
|
||||||
|
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
|
||||||
|
g_return_if_fail (!G_IS_PARAM_SPEC_OVERRIDE (pspec)); /* paranoid */
|
||||||
|
g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
|
||||||
|
|
||||||
|
install_property_internal (iface_class->g_type, 0, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
GParamSpec*
|
GParamSpec*
|
||||||
g_object_class_find_property (GObjectClass *class,
|
g_object_class_find_property (GObjectClass *class,
|
||||||
const gchar *property_name)
|
const gchar *property_name)
|
||||||
{
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
GParamSpec *redirect;
|
||||||
|
|
||||||
g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
|
g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
|
||||||
g_return_val_if_fail (property_name != NULL, NULL);
|
g_return_val_if_fail (property_name != NULL, NULL);
|
||||||
|
|
||||||
|
pspec = g_param_spec_pool_lookup (pspec_pool,
|
||||||
|
property_name,
|
||||||
|
G_OBJECT_CLASS_TYPE (class),
|
||||||
|
TRUE);
|
||||||
|
if (pspec)
|
||||||
|
{
|
||||||
|
redirect = g_param_spec_get_redirect_target (pspec);
|
||||||
|
if (redirect)
|
||||||
|
return redirect;
|
||||||
|
else
|
||||||
|
return pspec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
GParamSpec*
|
||||||
|
g_object_interface_find_property (gpointer g_iface,
|
||||||
|
const gchar *property_name)
|
||||||
|
{
|
||||||
|
GTypeInterface *iface_class = g_iface;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_class->g_type), NULL);
|
||||||
|
g_return_val_if_fail (property_name != NULL, NULL);
|
||||||
|
|
||||||
return g_param_spec_pool_lookup (pspec_pool,
|
return g_param_spec_pool_lookup (pspec_pool,
|
||||||
property_name,
|
property_name,
|
||||||
G_OBJECT_CLASS_TYPE (class),
|
iface_class->g_type,
|
||||||
TRUE);
|
FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
g_object_class_override_property (GObjectClass *oclass,
|
||||||
|
guint property_id,
|
||||||
|
const gchar *name)
|
||||||
|
{
|
||||||
|
GParamSpec *overridden = NULL;
|
||||||
|
GParamSpec *new;
|
||||||
|
GType parent_type;
|
||||||
|
|
||||||
|
g_return_if_fail (G_IS_OBJECT_CLASS (oclass));
|
||||||
|
g_return_if_fail (property_id > 0);
|
||||||
|
g_return_if_fail (name != NULL);
|
||||||
|
|
||||||
|
/* Find the overridden property; first check parent types
|
||||||
|
*/
|
||||||
|
parent_type = g_type_parent (G_OBJECT_CLASS_TYPE (oclass));
|
||||||
|
if (parent_type != G_TYPE_NONE)
|
||||||
|
overridden = g_param_spec_pool_lookup (pspec_pool,
|
||||||
|
name,
|
||||||
|
parent_type,
|
||||||
|
TRUE);
|
||||||
|
if (!overridden)
|
||||||
|
{
|
||||||
|
GType *ifaces;
|
||||||
|
guint n_ifaces;
|
||||||
|
|
||||||
|
/* Now check interfaces
|
||||||
|
*/
|
||||||
|
ifaces = g_type_interfaces (G_OBJECT_CLASS_TYPE (oclass), &n_ifaces);
|
||||||
|
while (n_ifaces-- && !overridden)
|
||||||
|
{
|
||||||
|
overridden = g_param_spec_pool_lookup (pspec_pool,
|
||||||
|
name,
|
||||||
|
ifaces[n_ifaces],
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (ifaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!overridden)
|
||||||
|
{
|
||||||
|
g_warning ("%s: Can't find property to override for '%s::%s'",
|
||||||
|
G_STRLOC, G_OBJECT_CLASS_NAME (oclass), name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new = g_param_spec_override (name, overridden);
|
||||||
|
g_object_class_install_property (oclass, property_id, new);
|
||||||
}
|
}
|
||||||
|
|
||||||
GParamSpec** /* free result */
|
GParamSpec** /* free result */
|
||||||
@ -330,6 +440,25 @@ g_object_class_list_properties (GObjectClass *class,
|
|||||||
return pspecs;
|
return pspecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GParamSpec** /* free result */
|
||||||
|
g_object_interface_list_properties (gpointer g_iface,
|
||||||
|
guint *n_properties_p)
|
||||||
|
{
|
||||||
|
GTypeInterface *iface_class = g_iface;
|
||||||
|
GParamSpec **pspecs;
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_TYPE_IS_INTERFACE (iface_class->g_type), NULL);
|
||||||
|
|
||||||
|
pspecs = g_param_spec_pool_list (pspec_pool,
|
||||||
|
iface_class->g_type,
|
||||||
|
&n);
|
||||||
|
if (n_properties_p)
|
||||||
|
*n_properties_p = n;
|
||||||
|
|
||||||
|
return pspecs;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_object_init (GObject *object)
|
g_object_init (GObject *object)
|
||||||
{
|
{
|
||||||
@ -491,10 +620,15 @@ g_object_notify (GObject *object,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
g_object_ref (object);
|
g_object_ref (object);
|
||||||
|
/* We don't need to get the redirect target
|
||||||
|
* (by, e.g. calling g_object_class_find_property())
|
||||||
|
* because g_object_notify_queue_add() does that
|
||||||
|
*/
|
||||||
pspec = g_param_spec_pool_lookup (pspec_pool,
|
pspec = g_param_spec_pool_lookup (pspec_pool,
|
||||||
property_name,
|
property_name,
|
||||||
G_OBJECT_TYPE (object),
|
G_OBJECT_TYPE (object),
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
if (!pspec)
|
if (!pspec)
|
||||||
g_warning ("%s: object class `%s' has no property named `%s'",
|
g_warning ("%s: object class `%s' has no property named `%s'",
|
||||||
G_STRLOC,
|
G_STRLOC,
|
||||||
@ -535,8 +669,14 @@ object_get_property (GObject *object,
|
|||||||
GValue *value)
|
GValue *value)
|
||||||
{
|
{
|
||||||
GObjectClass *class = g_type_class_peek (pspec->owner_type);
|
GObjectClass *class = g_type_class_peek (pspec->owner_type);
|
||||||
|
guint param_id = PARAM_SPEC_PARAM_ID (pspec);
|
||||||
|
GParamSpec *redirect;
|
||||||
|
|
||||||
|
redirect = g_param_spec_get_redirect_target (pspec);
|
||||||
|
if (redirect)
|
||||||
|
pspec = redirect;
|
||||||
|
|
||||||
class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec);
|
class->get_property (object, param_id, value, pspec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -547,6 +687,12 @@ object_set_property (GObject *object,
|
|||||||
{
|
{
|
||||||
GValue tmp_value = { 0, };
|
GValue tmp_value = { 0, };
|
||||||
GObjectClass *class = g_type_class_peek (pspec->owner_type);
|
GObjectClass *class = g_type_class_peek (pspec->owner_type);
|
||||||
|
guint param_id = PARAM_SPEC_PARAM_ID (pspec);
|
||||||
|
GParamSpec *redirect;
|
||||||
|
|
||||||
|
redirect = g_param_spec_get_redirect_target (pspec);
|
||||||
|
if (redirect)
|
||||||
|
pspec = redirect;
|
||||||
|
|
||||||
/* provide a copy to work from, convert (if necessary) and validate */
|
/* provide a copy to work from, convert (if necessary) and validate */
|
||||||
g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||||
@ -568,12 +714,93 @@ object_set_property (GObject *object,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
|
class->set_property (object, param_id, &tmp_value, pspec);
|
||||||
g_object_notify_queue_add (object, nqueue, pspec);
|
g_object_notify_queue_add (object, nqueue, pspec);
|
||||||
}
|
}
|
||||||
g_value_unset (&tmp_value);
|
g_value_unset (&tmp_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
object_interface_check_properties (gpointer func_data,
|
||||||
|
gpointer g_iface)
|
||||||
|
{
|
||||||
|
GTypeInterface *iface_class = g_iface;
|
||||||
|
GObjectClass *class = g_type_class_peek (iface_class->g_instance_type);
|
||||||
|
GType iface_type = iface_class->g_type;
|
||||||
|
GParamSpec **pspecs;
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
if (!G_IS_OBJECT_CLASS (class))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pspecs = g_param_spec_pool_list (pspec_pool, iface_type, &n);
|
||||||
|
|
||||||
|
while (n--)
|
||||||
|
{
|
||||||
|
GParamSpec *class_pspec = g_param_spec_pool_lookup (pspec_pool,
|
||||||
|
pspecs[n]->name,
|
||||||
|
G_OBJECT_CLASS_TYPE (class),
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
if (!class_pspec)
|
||||||
|
{
|
||||||
|
g_critical ("Object class %s doesn't implement property "
|
||||||
|
"'%s' from interface '%s'",
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (class)),
|
||||||
|
pspecs[n]->name,
|
||||||
|
g_type_name (iface_type));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The implementation paramspec must have a less restrictive
|
||||||
|
* type than the interface parameter spec for set() and a
|
||||||
|
* more restrictive type for get(). We just require equality,
|
||||||
|
* rather than doing something more complicated checking
|
||||||
|
* the READABLE and WRITABLE flags. We also simplify here
|
||||||
|
* by only checking the value type, not the G_PARAM_SPEC_TYPE.
|
||||||
|
*/
|
||||||
|
if (class_pspec &&
|
||||||
|
!g_type_is_a (G_PARAM_SPEC_VALUE_TYPE (pspecs[n]),
|
||||||
|
G_PARAM_SPEC_VALUE_TYPE (class_pspec)))
|
||||||
|
{
|
||||||
|
g_critical ("Property '%s' on class '%s' has type '%s' "
|
||||||
|
"which is different from the type '%s', "
|
||||||
|
"of the property on interface '%s'\n",
|
||||||
|
pspecs[n]->name,
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (class)),
|
||||||
|
g_type_name (G_PARAM_SPEC_VALUE_TYPE (class_pspec)),
|
||||||
|
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspecs[n])),
|
||||||
|
g_type_name (iface_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUBSET(a,b,mask) (((a) & ~(b) & (mask)) == 0)
|
||||||
|
|
||||||
|
/* CONSTRUCT and CONSTRUCT_ONLY add restrictions.
|
||||||
|
* READABLE and WRITABLE remove restrictions. The implementation
|
||||||
|
* paramspec must have less restrictive flags.
|
||||||
|
*/
|
||||||
|
if (class_pspec &&
|
||||||
|
(!SUBSET (class_pspec->flags,
|
||||||
|
pspecs[n]->flags,
|
||||||
|
G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY) ||
|
||||||
|
!SUBSET (pspecs[n]->flags,
|
||||||
|
class_pspec->flags,
|
||||||
|
G_PARAM_READABLE | G_PARAM_WRITABLE)))
|
||||||
|
{
|
||||||
|
g_critical ("Flags for property '%s' on class '%s' "
|
||||||
|
"are not compatible with the property on"
|
||||||
|
"interface '%s'\n",
|
||||||
|
pspecs[n]->name,
|
||||||
|
g_type_name (G_OBJECT_CLASS_TYPE (class)),
|
||||||
|
g_type_name (iface_type));
|
||||||
|
}
|
||||||
|
#undef SUBSET
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (pspecs);
|
||||||
|
}
|
||||||
|
|
||||||
gpointer
|
gpointer
|
||||||
g_object_new (GType object_type,
|
g_object_new (GType object_type,
|
||||||
const gchar *first_property_name,
|
const gchar *first_property_name,
|
||||||
|
@ -118,6 +118,17 @@ GParamSpec* g_object_class_find_property (GObjectClass *oclass,
|
|||||||
const gchar *property_name);
|
const gchar *property_name);
|
||||||
GParamSpec**g_object_class_list_properties (GObjectClass *oclass,
|
GParamSpec**g_object_class_list_properties (GObjectClass *oclass,
|
||||||
guint *n_properties);
|
guint *n_properties);
|
||||||
|
void g_object_class_override_property (GObjectClass *oclass,
|
||||||
|
guint property_id,
|
||||||
|
const gchar *name);
|
||||||
|
|
||||||
|
void g_object_interface_install_property (gpointer g_iface,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
GParamSpec* g_object_interface_find_property (gpointer g_iface,
|
||||||
|
const gchar *property_name);
|
||||||
|
GParamSpec**g_object_interface_list_properties (gpointer g_iface,
|
||||||
|
guint *n_properties_p);
|
||||||
|
|
||||||
gpointer g_object_new (GType object_type,
|
gpointer g_object_new (GType object_type,
|
||||||
const gchar *first_property_name,
|
const gchar *first_property_name,
|
||||||
...);
|
...);
|
||||||
|
@ -142,8 +142,14 @@ g_object_notify_queue_add (GObject *object,
|
|||||||
{
|
{
|
||||||
if (pspec->flags & G_PARAM_READABLE)
|
if (pspec->flags & G_PARAM_READABLE)
|
||||||
{
|
{
|
||||||
|
GParamSpec *redirect;
|
||||||
|
|
||||||
g_return_if_fail (nqueue->n_pspecs < 65535);
|
g_return_if_fail (nqueue->n_pspecs < 65535);
|
||||||
|
|
||||||
|
redirect = g_param_spec_get_redirect_target (pspec);
|
||||||
|
if (redirect)
|
||||||
|
pspec = redirect;
|
||||||
|
|
||||||
/* we do the deduping in _thaw */
|
/* we do the deduping in _thaw */
|
||||||
nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
|
nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
|
||||||
nqueue->n_pspecs++;
|
nqueue->n_pspecs++;
|
||||||
|
124
gobject/gparam.c
124
gobject/gparam.c
@ -22,7 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gparam.h"
|
#include "gparam.h"
|
||||||
|
#include "gparamspecs.h"
|
||||||
|
|
||||||
#include "gvaluecollector.h"
|
#include "gvaluecollector.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -246,7 +246,18 @@ g_param_spec_get_nick (GParamSpec *pspec)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
|
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
|
||||||
|
|
||||||
return pspec->_nick ? pspec->_nick : pspec->name;
|
if (pspec->_nick)
|
||||||
|
return pspec->_nick;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GParamSpec *redirect_target;
|
||||||
|
|
||||||
|
redirect_target = g_param_spec_get_redirect_target (pspec);
|
||||||
|
if (redirect_target && redirect_target->_nick)
|
||||||
|
return redirect_target->_nick;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pspec->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_CONST_RETURN gchar*
|
G_CONST_RETURN gchar*
|
||||||
@ -254,7 +265,18 @@ g_param_spec_get_blurb (GParamSpec *pspec)
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
|
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
|
||||||
|
|
||||||
return pspec->_blurb;
|
if (pspec->_blurb)
|
||||||
|
return pspec->_blurb;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GParamSpec *redirect_target;
|
||||||
|
|
||||||
|
redirect_target = g_param_spec_get_redirect_target (pspec);
|
||||||
|
if (redirect_target && redirect_target->_blurb)
|
||||||
|
return redirect_target->_blurb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -339,6 +361,21 @@ g_param_spec_steal_qdata (GParamSpec *pspec,
|
|||||||
return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
|
return g_datalist_id_remove_no_notify (&pspec->qdata, quark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GParamSpec*
|
||||||
|
g_param_spec_get_redirect_target (GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), NULL);
|
||||||
|
|
||||||
|
if (G_IS_PARAM_SPEC_OVERRIDE (pspec))
|
||||||
|
{
|
||||||
|
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
|
||||||
|
|
||||||
|
return ospec->overridden;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
g_param_value_set_default (GParamSpec *pspec,
|
g_param_value_set_default (GParamSpec *pspec,
|
||||||
GValue *value)
|
GValue *value)
|
||||||
@ -793,10 +830,10 @@ pspec_compare_id (gconstpointer a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline GSList*
|
static inline GSList*
|
||||||
pspec_list_remove_overridden (GSList *plist,
|
pspec_list_remove_overridden_and_redirected (GSList *plist,
|
||||||
GHashTable *ht,
|
GHashTable *ht,
|
||||||
GType owner_type,
|
GType owner_type,
|
||||||
guint *n_p)
|
guint *n_p)
|
||||||
{
|
{
|
||||||
GSList *rlist = NULL;
|
GSList *rlist = NULL;
|
||||||
|
|
||||||
@ -804,9 +841,31 @@ pspec_list_remove_overridden (GSList *plist,
|
|||||||
{
|
{
|
||||||
GSList *tmp = plist->next;
|
GSList *tmp = plist->next;
|
||||||
GParamSpec *pspec = plist->data;
|
GParamSpec *pspec = plist->data;
|
||||||
|
GParamSpec *found;
|
||||||
|
gboolean remove = FALSE;
|
||||||
|
|
||||||
if (param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE) != pspec)
|
/* Remove paramspecs that are redirected, and also paramspecs
|
||||||
g_slist_free_1 (plist);
|
* that have are overridden by non-redirected properties.
|
||||||
|
* The idea is to get the single paramspec for each name that
|
||||||
|
* best corresponds to what the application sees.
|
||||||
|
*/
|
||||||
|
if (g_param_spec_get_redirect_target (pspec))
|
||||||
|
remove = TRUE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
|
||||||
|
if (found != pspec)
|
||||||
|
{
|
||||||
|
GParamSpec *redirect = g_param_spec_get_redirect_target (found);
|
||||||
|
if (redirect != pspec)
|
||||||
|
remove = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remove)
|
||||||
|
{
|
||||||
|
g_slist_free_1 (plist);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
plist->next = rlist;
|
plist->next = rlist;
|
||||||
@ -830,12 +889,42 @@ pool_depth_list (gpointer key,
|
|||||||
|
|
||||||
if (g_type_is_a (owner_type, pspec->owner_type))
|
if (g_type_is_a (owner_type, pspec->owner_type))
|
||||||
{
|
{
|
||||||
guint d = g_type_depth (pspec->owner_type);
|
if (G_TYPE_IS_INTERFACE (pspec->owner_type))
|
||||||
|
{
|
||||||
|
slists[0] = g_slist_prepend (slists[0], pspec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
guint d = g_type_depth (pspec->owner_type);
|
||||||
|
|
||||||
slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
|
slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We handle interfaces specially since we don't want to
|
||||||
|
* count interface prerequsites like normal inheritance;
|
||||||
|
* the property comes from the direct inheritance from
|
||||||
|
* the prerequisite class, not from the interface that
|
||||||
|
* prerequires it.
|
||||||
|
*
|
||||||
|
* also 'depth' isn't a meaningful concept for interface
|
||||||
|
* prerequites.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
pool_depth_list_for_interface (gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec = value;
|
||||||
|
gpointer *data = user_data;
|
||||||
|
GSList **slists = data[0];
|
||||||
|
GType owner_type = (GType) data[1];
|
||||||
|
|
||||||
|
if (pspec->owner_type == owner_type)
|
||||||
|
slists[0] = g_slist_prepend (slists[0], pspec);
|
||||||
|
}
|
||||||
|
|
||||||
GParamSpec** /* free result */
|
GParamSpec** /* free result */
|
||||||
g_param_spec_pool_list (GParamSpecPool *pool,
|
g_param_spec_pool_list (GParamSpecPool *pool,
|
||||||
GType owner_type,
|
GType owner_type,
|
||||||
@ -856,10 +945,15 @@ g_param_spec_pool_list (GParamSpecPool *pool,
|
|||||||
slists = g_new0 (GSList*, d);
|
slists = g_new0 (GSList*, d);
|
||||||
data[0] = slists;
|
data[0] = slists;
|
||||||
data[1] = (gpointer) owner_type;
|
data[1] = (gpointer) owner_type;
|
||||||
g_hash_table_foreach (pool->hash_table, pool_depth_list, &data);
|
|
||||||
for (i = 0; i < d - 1; i++)
|
g_hash_table_foreach (pool->hash_table,
|
||||||
slists[i] = pspec_list_remove_overridden (slists[i], pool->hash_table, owner_type, n_pspecs_p);
|
G_TYPE_IS_INTERFACE (owner_type) ?
|
||||||
*n_pspecs_p += g_slist_length (slists[i]);
|
pool_depth_list_for_interface :
|
||||||
|
pool_depth_list,
|
||||||
|
&data);
|
||||||
|
|
||||||
|
for (i = 0; i < d; i++)
|
||||||
|
slists[i] = pspec_list_remove_overridden_and_redirected (slists[i], pool->hash_table, owner_type, n_pspecs_p);
|
||||||
pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
|
pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
|
||||||
p = pspecs;
|
p = pspecs;
|
||||||
for (i = 0; i < d; i++)
|
for (i = 0; i < d; i++)
|
||||||
|
@ -73,7 +73,7 @@ struct _GParamSpec
|
|||||||
gchar *name;
|
gchar *name;
|
||||||
GParamFlags flags;
|
GParamFlags flags;
|
||||||
GType value_type;
|
GType value_type;
|
||||||
GType owner_type; /* class using this property */
|
GType owner_type; /* class or interface using this property */
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gchar *_nick;
|
gchar *_nick;
|
||||||
@ -122,6 +122,8 @@ void g_param_spec_set_qdata_full (GParamSpec *pspec,
|
|||||||
GDestroyNotify destroy);
|
GDestroyNotify destroy);
|
||||||
gpointer g_param_spec_steal_qdata (GParamSpec *pspec,
|
gpointer g_param_spec_steal_qdata (GParamSpec *pspec,
|
||||||
GQuark quark);
|
GQuark quark);
|
||||||
|
GParamSpec* g_param_spec_get_redirect_target (GParamSpec *pspec);
|
||||||
|
|
||||||
void g_param_value_set_default (GParamSpec *pspec,
|
void g_param_value_set_default (GParamSpec *pspec,
|
||||||
GValue *value);
|
GValue *value);
|
||||||
gboolean g_param_value_defaults (GParamSpec *pspec,
|
gboolean g_param_value_defaults (GParamSpec *pspec,
|
||||||
|
@ -966,6 +966,54 @@ param_object_values_cmp (GParamSpec *pspec,
|
|||||||
return p1 < p2 ? -1 : p1 > p2;
|
return p1 < p2 ? -1 : p1 > p2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
param_override_init (GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
/* GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec); */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
param_override_finalize (GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
|
||||||
|
GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_OVERRIDE));
|
||||||
|
|
||||||
|
if (ospec->overridden)
|
||||||
|
{
|
||||||
|
g_param_spec_unref (ospec->overridden);
|
||||||
|
ospec->overridden = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_class->finalize (pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
param_override_set_default (GParamSpec *pspec,
|
||||||
|
GValue *value)
|
||||||
|
{
|
||||||
|
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
|
||||||
|
|
||||||
|
g_param_value_set_default (ospec->overridden, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
param_override_validate (GParamSpec *pspec,
|
||||||
|
GValue *value)
|
||||||
|
{
|
||||||
|
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
|
||||||
|
|
||||||
|
return g_param_value_validate (ospec->overridden, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint
|
||||||
|
param_override_values_cmp (GParamSpec *pspec,
|
||||||
|
const GValue *value1,
|
||||||
|
const GValue *value2)
|
||||||
|
{
|
||||||
|
GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
|
||||||
|
|
||||||
|
return g_param_values_cmp (ospec->overridden, value1, value2);
|
||||||
|
}
|
||||||
|
|
||||||
/* --- type initialization --- */
|
/* --- type initialization --- */
|
||||||
GType *g_param_spec_types = NULL;
|
GType *g_param_spec_types = NULL;
|
||||||
@ -973,7 +1021,7 @@ GType *g_param_spec_types = NULL;
|
|||||||
void
|
void
|
||||||
g_param_spec_types_init (void) /* sync with gtype.c */
|
g_param_spec_types_init (void) /* sync with gtype.c */
|
||||||
{
|
{
|
||||||
const guint n_types = 20;
|
const guint n_types = 21;
|
||||||
GType type, *spec_types, *spec_types_bound;
|
GType type, *spec_types, *spec_types_bound;
|
||||||
|
|
||||||
g_param_spec_types = g_new0 (GType, n_types);
|
g_param_spec_types = g_new0 (GType, n_types);
|
||||||
@ -1341,6 +1389,24 @@ g_param_spec_types_init (void) /* sync with gtype.c */
|
|||||||
g_assert (type == G_TYPE_PARAM_OBJECT);
|
g_assert (type == G_TYPE_PARAM_OBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* G_TYPE_PARAM_OVERRIDE
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
static const GParamSpecTypeInfo pspec_info = {
|
||||||
|
sizeof (GParamSpecOverride), /* instance_size */
|
||||||
|
16, /* n_preallocs */
|
||||||
|
param_override_init, /* instance_init */
|
||||||
|
G_TYPE_NONE, /* value_type */
|
||||||
|
param_override_finalize, /* finalize */
|
||||||
|
param_override_set_default, /* value_set_default */
|
||||||
|
param_override_validate, /* value_validate */
|
||||||
|
param_override_values_cmp, /* values_cmp */
|
||||||
|
};
|
||||||
|
type = g_param_type_register_static ("GParamOverride", &pspec_info);
|
||||||
|
*spec_types++ = type;
|
||||||
|
g_assert (type == G_TYPE_PARAM_OVERRIDE);
|
||||||
|
}
|
||||||
|
|
||||||
g_assert (spec_types == spec_types_bound);
|
g_assert (spec_types == spec_types_bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1831,3 +1897,33 @@ g_param_spec_object (const gchar *name,
|
|||||||
|
|
||||||
return G_PARAM_SPEC (ospec);
|
return G_PARAM_SPEC (ospec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GParamSpec*
|
||||||
|
g_param_spec_override (const gchar *name,
|
||||||
|
GParamSpec *overridden)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
g_return_val_if_fail (name != NULL, NULL);
|
||||||
|
g_return_val_if_fail (G_IS_PARAM_SPEC (overridden), NULL);
|
||||||
|
|
||||||
|
/* Dereference further redirections for property that was passed in
|
||||||
|
*/
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
GParamSpec *indirect = g_param_spec_get_redirect_target (overridden);
|
||||||
|
if (indirect)
|
||||||
|
overridden = indirect;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pspec = g_param_spec_internal (G_TYPE_PARAM_OVERRIDE,
|
||||||
|
name, NULL, NULL,
|
||||||
|
overridden->flags);
|
||||||
|
|
||||||
|
pspec->value_type = G_PARAM_SPEC_VALUE_TYPE (overridden);
|
||||||
|
G_PARAM_SPEC_OVERRIDE (pspec)->overridden = g_param_spec_ref (overridden);
|
||||||
|
|
||||||
|
return pspec;
|
||||||
|
}
|
||||||
|
@ -93,6 +93,9 @@ G_BEGIN_DECLS
|
|||||||
#define G_TYPE_PARAM_OBJECT (g_param_spec_types[19])
|
#define G_TYPE_PARAM_OBJECT (g_param_spec_types[19])
|
||||||
#define G_IS_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT))
|
#define G_IS_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OBJECT))
|
||||||
#define G_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject))
|
#define G_PARAM_SPEC_OBJECT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OBJECT, GParamSpecObject))
|
||||||
|
#define G_TYPE_PARAM_OVERRIDE (g_param_spec_types[20])
|
||||||
|
#define G_IS_PARAM_SPEC_OVERRIDE(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), G_TYPE_PARAM_OVERRIDE))
|
||||||
|
#define G_PARAM_SPEC_OVERRIDE(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), G_TYPE_PARAM_OVERRIDE, GParamSpecOverride))
|
||||||
|
|
||||||
|
|
||||||
/* --- typedefs & structures --- */
|
/* --- typedefs & structures --- */
|
||||||
@ -116,6 +119,7 @@ typedef struct _GParamSpecBoxed GParamSpecBoxed;
|
|||||||
typedef struct _GParamSpecPointer GParamSpecPointer;
|
typedef struct _GParamSpecPointer GParamSpecPointer;
|
||||||
typedef struct _GParamSpecValueArray GParamSpecValueArray;
|
typedef struct _GParamSpecValueArray GParamSpecValueArray;
|
||||||
typedef struct _GParamSpecObject GParamSpecObject;
|
typedef struct _GParamSpecObject GParamSpecObject;
|
||||||
|
typedef struct _GParamSpecOverride GParamSpecOverride;
|
||||||
|
|
||||||
struct _GParamSpecChar
|
struct _GParamSpecChar
|
||||||
{
|
{
|
||||||
@ -258,6 +262,12 @@ struct _GParamSpecObject
|
|||||||
{
|
{
|
||||||
GParamSpec parent_instance;
|
GParamSpec parent_instance;
|
||||||
};
|
};
|
||||||
|
struct _GParamSpecOverride
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GParamSpec parent_instance;
|
||||||
|
GParamSpec *overridden;
|
||||||
|
};
|
||||||
|
|
||||||
/* --- GParamSpec prototypes --- */
|
/* --- GParamSpec prototypes --- */
|
||||||
GParamSpec* g_param_spec_char (const gchar *name,
|
GParamSpec* g_param_spec_char (const gchar *name,
|
||||||
@ -382,6 +392,8 @@ GParamSpec* g_param_spec_object (const gchar *name,
|
|||||||
GType object_type,
|
GType object_type,
|
||||||
GParamFlags flags);
|
GParamFlags flags);
|
||||||
|
|
||||||
|
GParamSpec* g_param_spec_override (const gchar *name,
|
||||||
|
GParamSpec *overridden);
|
||||||
|
|
||||||
/* --- internal --- */
|
/* --- internal --- */
|
||||||
/* We prefix variable declarations so they can
|
/* We prefix variable declarations so they can
|
||||||
|
Loading…
x
Reference in New Issue
Block a user