diff --git a/docs/reference/glib/tmpl/macros_misc.sgml b/docs/reference/glib/tmpl/macros_misc.sgml
index 7b93d0a7e..cd71ee73b 100644
--- a/docs/reference/glib/tmpl/macros_misc.sgml
+++ b/docs/reference/glib/tmpl/macros_misc.sgml
@@ -71,6 +71,7 @@ arrays or arrays on the stack.
Portable way to copy va_list variables.
+
@ap1: the va_list variable to place a copy of @ap2 in.
@ap2: a va_list.
diff --git a/docs/reference/gobject/tmpl/gboxed.sgml b/docs/reference/gobject/tmpl/gboxed.sgml
index 0e6835741..87183cbca 100644
--- a/docs/reference/gobject/tmpl/gboxed.sgml
+++ b/docs/reference/gobject/tmpl/gboxed.sgml
@@ -14,12 +14,6 @@ gboxed
-
-
-
-
-
-
diff --git a/docs/reference/gobject/tmpl/gobject-unused.sgml b/docs/reference/gobject/tmpl/gobject-unused.sgml
index 0f00a4544..fcb15763b 100644
--- a/docs/reference/gobject/tmpl/gobject-unused.sgml
+++ b/docs/reference/gobject/tmpl/gobject-unused.sgml
@@ -1,3 +1,9 @@
+
+
+
+
+
+
diff --git a/docs/reference/gobject/tmpl/param_specs.sgml b/docs/reference/gobject/tmpl/param_specs.sgml
index d57c0a40c..fa1123f70 100644
--- a/docs/reference/gobject/tmpl/param_specs.sgml
+++ b/docs/reference/gobject/tmpl/param_specs.sgml
@@ -25,6 +25,7 @@ Parameter Specifications
@blurb:
@flags:
@value_type:
+@owner_type:
diff --git a/glib/gbsearcharray.h b/glib/gbsearcharray.h
index e4b9201e9..1682a7606 100644
--- a/glib/gbsearcharray.h
+++ b/glib/gbsearcharray.h
@@ -26,7 +26,7 @@
G_BEGIN_DECLS
/* helper macro to avoid signed overflow for value comparisions */
-#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) < (v2) ? -1 : (v1) > (v2) ? 1 : 0)
+#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) < (v2) ? -1 : (v1) > (v2))
/* --- typedefs --- */
diff --git a/gobject/ChangeLog b/gobject/ChangeLog
index 9a107afb0..1993ca34e 100644
--- a/gobject/ChangeLog
+++ b/gobject/ChangeLog
@@ -1,3 +1,24 @@
+Mon Jun 11 17:07:06 2001 Tim Janik
+
+ * gboxed.[hc]: remove left-over usages of an anonymous GBoxed typedef.
+
+ * gobjectnotifyqueue.c: moved property notify queue implementation
+ bits into this function.
+
+ * gparam.[hc]: added g_param_spec_pool_belongings(), completed
+ g_param_spec_pool_list(). added GParameter for _setv() functions.
+
+ * gobject.[hc]: use gobjectnotifyqueue.h implementation now.
+ got rid of properties_changed signal.
+ new functions g_object_newv(), g_object_class_list_properties().
+ removed "properties_changed" signal.
+
+ * gtype.[hc]: added g_type_depth() to figure number of parent
+ types + 1 for a type.
+
+ * gsignal.h: add g_signal_connect() (as per owen's request) and
+ g_signal_connect_swapped().
+
2001-06-13 Havoc Pennington
* Makefile.am (progs_LDADD): link to ./libgobject-1.3.la
diff --git a/gobject/Makefile.am b/gobject/Makefile.am
index 471b4ab96..22126089e 100644
--- a/gobject/Makefile.am
+++ b/gobject/Makefile.am
@@ -52,9 +52,11 @@ gruntime_public_h_sources = @STRIP_BEGIN@ \
gvaluearray.h \
gvaluecollector.h \
gvaluetypes.h \
+ gobjectnotifyqueue.c \
@STRIP_END@
# GRuntime header files that don't get installed
-gruntime_private_h_sources =
+gruntime_private_h_sources = @STRIP_BEGIN@ \
+@STRIP_END@
# GRuntime C sources to build the library from
gruntime_c_sources = @STRIP_BEGIN@ \
gboxed.c \
diff --git a/gobject/gboxed.c b/gobject/gboxed.c
index 82fe36d7b..e61429aaf 100644
--- a/gobject/gboxed.c
+++ b/gobject/gboxed.c
@@ -333,7 +333,7 @@ g_boxed_type_register_static (const gchar *name,
return type;
}
-GBoxed*
+gpointer
g_boxed_copy (GType boxed_type,
gconstpointer src_boxed)
{
diff --git a/gobject/gboxed.h b/gobject/gboxed.h
index 742fd1d44..1ab9f7ee4 100644
--- a/gobject/gboxed.h
+++ b/gobject/gboxed.h
@@ -29,14 +29,13 @@ G_BEGIN_DECLS
/* --- typedefs --- */
-typedef struct _GBoxed GBoxed;
typedef gpointer (*GBoxedInitFunc) (void);
typedef gpointer (*GBoxedCopyFunc) (gpointer boxed);
typedef void (*GBoxedFreeFunc) (gpointer boxed);
/* --- prototypes --- */
-GBoxed* g_boxed_copy (GType boxed_type,
+gpointer g_boxed_copy (GType boxed_type,
gconstpointer src_boxed);
void g_boxed_free (GType boxed_type,
gpointer boxed);
diff --git a/gobject/gbsearcharray.h b/gobject/gbsearcharray.h
index e4b9201e9..1682a7606 100644
--- a/gobject/gbsearcharray.h
+++ b/gobject/gbsearcharray.h
@@ -26,7 +26,7 @@
G_BEGIN_DECLS
/* helper macro to avoid signed overflow for value comparisions */
-#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) < (v2) ? -1 : (v1) > (v2) ? 1 : 0)
+#define G_BSEARCH_ARRAY_CMP(v1,v2) ((v1) < (v2) ? -1 : (v1) > (v2))
/* --- typedefs --- */
diff --git a/gobject/gobject.c b/gobject/gobject.c
index e7e4566d5..0cb27a059 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -16,18 +16,17 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
+#include "gobject.h"
/*
* MT safe
*/
-#include "gobject.h"
-
-
#include "gvaluecollector.h"
#include "gsignal.h"
#include "gparamspecs.h"
#include "gvaluetypes.h"
+#include "gobjectnotifyqueue.c"
#include
@@ -35,7 +34,8 @@
/* --- macros --- */
-#define PARAM_SPEC_PARAM_ID(pspec) (GPOINTER_TO_UINT (g_param_spec_get_qdata ((pspec), quark_property_id)))
+#define PARAM_SPEC_PARAM_ID(pspec) ((pspec)->param_id)
+#define PARAM_SPEC_SET_PARAM_ID(pspec, id) ((pspec)->param_id = (id))
/* --- signals --- */
@@ -52,10 +52,6 @@ enum {
};
-/* --- typedefs --- */
-typedef struct _NotifyQueue NotifyQueue;
-
-
/* --- prototypes --- */
static void g_object_base_class_init (GObjectClass *class);
static void g_object_base_class_finalize (GObjectClass *class);
@@ -93,41 +89,23 @@ static gchar* g_value_object_lcopy_value (const GValue *value,
static void g_object_dispatch_properties_changed (GObject *object,
guint n_pspecs,
GParamSpec **pspecs);
-static void g_object_properties_changed (GObject *object,
- guint n_pspecs,
- GParamSpec **pspecs);
-static void g_object_notify_property_changed (GObject *object,
- GParamSpec *pspec);
-static inline NotifyQueue* object_freeze_notifies (GObject *object);
-static inline void object_queue_property (GObject *object,
- GParamSpec *pspec,
- NotifyQueue *nqueue);
-static inline void object_thaw_notifies (GObject *object,
- NotifyQueue *nqueue);
static inline void object_get_property (GObject *object,
GParamSpec *pspec,
GValue *value);
static inline void object_set_property (GObject *object,
GParamSpec *pspec,
const GValue *value,
- NotifyQueue *nqueue);
+ GObjectNotifyQueue *nqueue);
/* --- structures --- */
-struct _NotifyQueue
-{
- GSList *pspecs;
- guint n_pspecs;
- guint freeze_count;
-};
/* --- variables --- */
-static GQuark quark_notify_queue = 0;
-static GQuark quark_property_id = 0;
-static GQuark quark_closure_array = 0;
-static GParamSpecPool *pspec_pool = NULL;
-static gulong gobject_signals[LAST_SIGNAL] = { 0, };
+static GQuark quark_closure_array = 0;
+static GParamSpecPool *pspec_pool = NULL;
+static GObjectNotifyContext property_notify_context = { 0, };
+static gulong gobject_signals[LAST_SIGNAL] = { 0, };
/* --- functions --- */
@@ -218,8 +196,6 @@ g_object_base_class_init (GObjectClass *class)
GObjectClass *pclass = g_type_class_peek_parent (class);
/* reset instance specific fields and methods that don't get inherited */
- class->n_property_specs = 0;
- class->property_specs = NULL;
class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
class->get_property = NULL;
class->set_property = NULL;
@@ -228,7 +204,7 @@ g_object_base_class_init (GObjectClass *class)
static void
g_object_base_class_finalize (GObjectClass *class)
{
- guint i;
+ GList *list, *node;
g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
@@ -236,26 +212,33 @@ g_object_base_class_finalize (GObjectClass *class)
g_slist_free (class->construct_properties);
class->construct_properties = NULL;
- for (i = 0; i < class->n_property_specs; i++)
+ list = g_param_spec_pool_belongings (pspec_pool, G_OBJECT_CLASS_TYPE (class));
+ for (node = list; node; node = node->next)
{
- GParamSpec *pspec = class->property_specs[i];
+ GParamSpec *pspec = node->data;
g_param_spec_pool_remove (pspec_pool, pspec);
- g_param_spec_set_qdata (pspec, quark_property_id, NULL);
+ PARAM_SPEC_SET_PARAM_ID (pspec, 0);
g_param_spec_unref (pspec);
}
- class->n_property_specs = 0;
- g_free (class->property_specs);
- class->property_specs = NULL;
+ g_list_free (list);
+}
+
+static void
+g_object_notify_dispatcher (GObject *object,
+ guint n_pspecs,
+ GParamSpec **pspecs)
+{
+ G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
}
static void
g_object_do_class_init (GObjectClass *class)
{
- quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
- quark_property_id = g_quark_from_static_string ("GObject-property-id");
quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
pspec_pool = g_param_spec_pool_new (TRUE);
+ property_notify_context.quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
+ property_notify_context.dispatcher = g_object_notify_dispatcher;
class->constructor = g_object_constructor;
class->set_property = g_object_do_set_property;
@@ -263,18 +246,8 @@ g_object_do_class_init (GObjectClass *class)
class->shutdown = g_object_shutdown;
class->finalize = g_object_finalize;
class->dispatch_properties_changed = g_object_dispatch_properties_changed;
- class->properties_changed = g_object_properties_changed;
- class->notify = g_object_notify_property_changed;
+ class->notify = NULL;
- gobject_signals[PROPERTIES_CHANGED] =
- g_signal_newc ("properties_changed",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE,
- G_STRUCT_OFFSET (GObjectClass, properties_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__UINT_POINTER,
- G_TYPE_NONE,
- 2, G_TYPE_UINT, G_TYPE_POINTER);
gobject_signals[NOTIFY] =
g_signal_newc ("notify",
G_TYPE_FROM_CLASS (class),
@@ -291,8 +264,6 @@ g_object_class_install_property (GObjectClass *class,
guint property_id,
GParamSpec *pspec)
{
- guint i;
-
g_return_if_fail (G_IS_OBJECT_CLASS (class));
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
if (pspec->flags & G_PARAM_WRITABLE)
@@ -306,18 +277,6 @@ g_object_class_install_property (GObjectClass *class,
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
- /* expensive paranoia checks ;( */
- for (i = 0; i < class->n_property_specs; i++)
- if (PARAM_SPEC_PARAM_ID (class->property_specs[i]) == property_id)
- {
- g_warning (G_STRLOC ": class `%s' already contains a property `%s' with id %u, "
- "cannot install property `%s'",
- G_OBJECT_CLASS_NAME (class),
- class->property_specs[i]->name,
- property_id,
- pspec->name);
- return;
- }
if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE))
{
g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
@@ -328,11 +287,8 @@ g_object_class_install_property (GObjectClass *class,
g_param_spec_ref (pspec);
g_param_spec_sink (pspec);
- g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
+ PARAM_SPEC_SET_PARAM_ID (pspec, property_id);
g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
- i = class->n_property_specs++;
- class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
- class->property_specs[i] = pspec;
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
@@ -357,42 +313,22 @@ g_object_class_find_property (GObjectClass *class,
TRUE);
}
-static void
-free_notify_queue (gpointer data)
+GParamSpec** /* free result */
+g_object_class_list_properties (GObjectClass *class,
+ guint *n_properties_p)
{
- NotifyQueue *nqueue = data;
-
- g_slist_free (nqueue->pspecs);
- g_free (nqueue);
-}
+ GParamSpec **pspecs;
+ guint n;
-static inline NotifyQueue*
-object_freeze_notifies (GObject *object)
-{
- NotifyQueue *nqueue;
+ g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
- nqueue = g_object_get_qdata (object, quark_notify_queue);
- if (!nqueue)
- {
- nqueue = g_new0 (NotifyQueue, 1);
- g_object_set_qdata_full (object, quark_notify_queue, nqueue, free_notify_queue);
- }
- nqueue->freeze_count++;
+ pspecs = g_param_spec_pool_list (pspec_pool,
+ G_OBJECT_CLASS_TYPE (class),
+ &n);
+ if (n_properties_p)
+ *n_properties_p = n;
- return nqueue;
-}
-
-static inline void
-object_queue_property (GObject *object,
- GParamSpec *pspec,
- NotifyQueue *nqueue)
-{
- if (pspec->flags & G_PARAM_READABLE)
- {
- /* we will dedup later */
- nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
- nqueue->n_pspecs++;
- }
+ return pspecs;
}
static void
@@ -401,8 +337,8 @@ g_object_init (GObject *object)
object->ref_count = 1;
g_datalist_init (&object->qdata);
- /* freeze object's notification queue, g_object_new_valist() takes care of that */
- object_freeze_notifies (object);
+ /* freeze object's notification queue, g_object_newv() preserves pairedness */
+ g_object_notify_queue_freeze (object, &property_notify_context);
#ifdef G_ENABLE_DEBUG
IF_DEBUG (OBJECTS)
@@ -505,54 +441,10 @@ g_object_finalize (GObject *object)
#endif /* G_ENABLE_DEBUG */
}
-static inline void
-object_thaw_notifies (GObject *object,
- NotifyQueue *nqueue)
-{
- GParamSpec **pspecs;
- GSList *slist;
- guint n_pspecs = 0;
-
- nqueue->freeze_count--;
- if (nqueue->freeze_count)
- return;
- g_return_if_fail (object->ref_count > 0);
-
- pspecs = g_new (GParamSpec*, nqueue->n_pspecs);
- for (slist = nqueue->pspecs; slist; slist = slist->next)
- {
- GParamSpec *pspec = slist->data;
- gint i = 0;
-
- /* dedup, make pspecs in the list unique */
- redo_dedup_check:
- if (pspecs[i] == pspec)
- continue;
- if (++i < n_pspecs)
- goto redo_dedup_check;
-
- pspecs[n_pspecs++] = pspec;
- }
- g_object_set_qdata (object, quark_notify_queue, NULL);
-
- if (n_pspecs)
- G_OBJECT_GET_CLASS (object)->dispatch_properties_changed (object, n_pspecs, pspecs);
-
- g_free (pspecs);
-}
-
static void
g_object_dispatch_properties_changed (GObject *object,
guint n_pspecs,
GParamSpec **pspecs)
-{
- g_signal_emit (object, gobject_signals[PROPERTIES_CHANGED], 0, n_pspecs, pspecs);
-}
-
-static void
-g_object_properties_changed (GObject *object,
- guint n_pspecs,
- GParamSpec **pspecs)
{
guint i;
@@ -560,16 +452,6 @@ g_object_properties_changed (GObject *object,
g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
}
-static void
-g_object_notify_property_changed (GObject *object,
- GParamSpec *pspec)
-{
- if (0) /* FIXME */
- g_message ("NOTIFICATION: property `%s' changed on object `%s'",
- pspec->name,
- G_OBJECT_TYPE_NAME (object));
-}
-
void
g_object_freeze_notify (GObject *object)
{
@@ -578,7 +460,7 @@ g_object_freeze_notify (GObject *object)
return;
g_object_ref (object);
- object_freeze_notifies (object);
+ g_object_notify_queue_freeze (object, &property_notify_context);
g_object_unref (object);
}
@@ -605,10 +487,10 @@ g_object_notify (GObject *object,
property_name);
else
{
- NotifyQueue *nqueue = object_freeze_notifies (object);
+ GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
- object_queue_property (object, pspec, nqueue);
- object_thaw_notifies (object, nqueue);
+ g_object_notify_queue_add (object, nqueue, pspec);
+ g_object_notify_queue_thaw (object, nqueue);
}
g_object_unref (object);
}
@@ -616,19 +498,19 @@ g_object_notify (GObject *object,
void
g_object_thaw_notify (GObject *object)
{
- NotifyQueue *nqueue;
+ GObjectNotifyQueue *nqueue;
g_return_if_fail (G_IS_OBJECT (object));
if (!object->ref_count)
return;
g_object_ref (object);
- nqueue = g_object_get_qdata (object, quark_notify_queue);
+ nqueue = g_object_notify_queue_from_object (object, &property_notify_context);
if (!nqueue || !nqueue->freeze_count)
g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen",
G_OBJECT_TYPE_NAME (object), object);
else
- object_thaw_notifies (object, nqueue);
+ g_object_notify_queue_thaw (object, nqueue);
g_object_unref (object);
}
@@ -637,18 +519,16 @@ object_get_property (GObject *object,
GParamSpec *pspec,
GValue *value)
{
- GObjectClass *class;
-
- class = g_type_class_peek (pspec->owner_type);
+ GObjectClass *class = g_type_class_peek (pspec->owner_type);
class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec);
}
static inline void
-object_set_property (GObject *object,
- GParamSpec *pspec,
- const GValue *value,
- NotifyQueue *nqueue)
+object_set_property (GObject *object,
+ GParamSpec *pspec,
+ const GValue *value,
+ GObjectNotifyQueue *nqueue)
{
GValue tmp_value = { 0, };
GObjectClass *class = g_type_class_peek (pspec->owner_type);
@@ -674,7 +554,7 @@ object_set_property (GObject *object,
else
{
class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec);
- object_queue_property (object, pspec, nqueue);
+ g_object_notify_queue_add (object, nqueue, pspec);
}
g_value_unset (&tmp_value);
}
@@ -696,36 +576,159 @@ g_object_new (GType object_type,
return object;
}
+gpointer
+g_object_newv (GType object_type,
+ guint n_parameters,
+ GParameter *parameters)
+{
+ GObjectConstructParam *cparams, *oparams;
+ GObjectNotifyQueue *nqueue;
+ GObject *object;
+ GObjectClass *class;
+ GSList *slist;
+ guint n_total_cparams = 0, n_cparams = 0, n_oparams = 0, n_cvalues;
+ GValue *cvalues;
+ GList *clist = NULL;
+ guint i;
+
+ g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+
+ class = g_type_class_ref (object_type);
+ for (slist = class->construct_properties; slist; slist = slist->next)
+ {
+ clist = g_list_prepend (clist, slist->data);
+ n_total_cparams += 1;
+ }
+
+ /* collect parameters, sort into construction and normal ones */
+ oparams = g_new (GObjectConstructParam, n_parameters);
+ cparams = g_new (GObjectConstructParam, n_total_cparams);
+ for (i = 0; i < n_parameters; i++)
+ {
+ GValue *value = ¶meters[i].value;
+ GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool,
+ parameters[i].name,
+ object_type,
+ TRUE);
+ if (!pspec)
+ {
+ g_warning ("%s: object class `%s' has no property named `%s'",
+ G_STRLOC,
+ g_type_name (object_type),
+ parameters[i].name);
+ continue;
+ }
+ if (!(pspec->flags & G_PARAM_WRITABLE))
+ {
+ g_warning ("%s: property `%s' of object class `%s' is not writable",
+ G_STRLOC,
+ pspec->name,
+ g_type_name (object_type));
+ continue;
+ }
+ if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+ {
+ GList *list = g_list_find (clist, pspec);
+
+ if (!list)
+ {
+ g_warning (G_STRLOC ": construct property \"%s\" for object `%s' can't be set twice",
+ pspec->name, g_type_name (object_type));
+ continue;
+ }
+ cparams[n_cparams].pspec = pspec;
+ cparams[n_cparams].value = value;
+ n_cparams++;
+ if (!list->prev)
+ clist = list->next;
+ else
+ list->prev->next = list->next;
+ if (list->next)
+ list->next->prev = list->prev;
+ g_list_free_1 (list);
+ }
+ else
+ {
+ oparams[n_oparams].pspec = pspec;
+ oparams[n_oparams].value = value;
+ n_oparams++;
+ }
+ }
+
+ /* set remaining construction properties to default values */
+ n_cvalues = n_total_cparams - n_cparams;
+ cvalues = g_new (GValue, n_cvalues);
+ while (clist)
+ {
+ GList *tmp = clist->next;
+ GParamSpec *pspec = clist->data;
+ GValue *value = cvalues + n_total_cparams - n_cparams - 1;
+
+ value->g_type = 0;
+ g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_param_value_set_default (pspec, value);
+
+ cparams[n_cparams].pspec = pspec;
+ cparams[n_cparams].value = value;
+ n_cparams++;
+
+ g_list_free_1 (clist);
+ clist = tmp;
+ }
+
+ /* construct object from construction parameters */
+ object = class->constructor (object_type, n_total_cparams, cparams);
+
+ /* free construction values */
+ g_free (cparams);
+ while (n_cvalues--)
+ g_value_unset (cvalues + n_cvalues);
+ g_free (cvalues);
+
+ /* release g_object_init() notification queue freeze_count */
+ nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
+ g_object_notify_queue_thaw (object, nqueue);
+
+ /* set remaining properties */
+ for (i = 0; i < n_oparams; i++)
+ object_set_property (object, oparams[i].pspec, oparams[i].value, nqueue);
+ g_free (oparams);
+
+ g_type_class_unref (class);
+
+ /* release our own freeze count and handle notifications */
+ g_object_notify_queue_thaw (object, nqueue);
+
+ return object;
+}
+
gpointer
g_object_new_valist (GType object_type,
const gchar *first_property_name,
va_list var_args)
{
- NotifyQueue *nqueue;
- GObject *object;
GObjectClass *class;
+ GParameter *params;
const gchar *name;
- GObjectConstructParam *cparams = NULL, *nparams = NULL;
- guint n_cparams = 0, n_nparams = 0;
- GSList *clist;
+ GObject *object;
+ guint n_params = 0, n_alloced_params = 16;
g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
- class = g_type_class_ref (object_type);
- clist = g_slist_copy (class->construct_properties);
+ if (!first_property_name)
+ return g_object_newv (object_type, 0, NULL);
- /* collect parameters, sort into construction and normal ones */
+ class = g_type_class_ref (object_type);
+
+ params = g_new (GParameter, n_alloced_params);
name = first_property_name;
while (name)
{
- GValue *value;
- GParamSpec *pspec;
gchar *error = NULL;
-
- pspec = g_param_spec_pool_lookup (pspec_pool,
- name,
- object_type,
- TRUE);
+ GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool,
+ name,
+ object_type,
+ TRUE);
if (!pspec)
{
g_warning ("%s: object class `%s' has no property named `%s'",
@@ -734,19 +737,15 @@ g_object_new_valist (GType object_type,
name);
break;
}
- if (!(pspec->flags & G_PARAM_WRITABLE))
+ if (n_params >= n_alloced_params)
{
- g_warning ("%s: property `%s' of object class `%s' is not writable",
- G_STRLOC,
- pspec->name,
- g_type_name (object_type));
- break;
+ n_alloced_params += 16;
+ params = g_renew (GParameter, params, n_alloced_params);
}
-
- value = g_new (GValue, 1);
- value->g_type = 0;
- g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- G_VALUE_COLLECT (value, var_args, 0, &error);
+ params[n_params].name = name;
+ params[n_params].value.g_type = 0;
+ g_value_init (¶ms[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ G_VALUE_COLLECT (¶ms[n_params].value, var_args, 0, &error);
if (error)
{
g_warning ("%s: %s", G_STRLOC, error);
@@ -757,86 +756,18 @@ g_object_new_valist (GType object_type,
*/
break;
}
- if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
- {
- guint i;
-
- if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
- cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
- cparams[n_cparams].pspec = pspec;
- cparams[n_cparams].value = value;
- for (i = 0; i < n_cparams; i++) /* picky, aren't we? ;) */
- if (cparams[i].pspec == pspec)
- g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
- pspec->name, g_type_name (object_type));
- n_cparams++;
- clist = g_slist_remove (clist, pspec); /* FIXME: unique */
- }
- else
- {
- if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
- nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
- nparams[n_nparams].pspec = pspec;
- nparams[n_nparams].value = value;
- n_nparams++;
- }
-
+ n_params++;
name = va_arg (var_args, gchar*);
}
- /* construct object from construction parameters */
- while (clist)
- {
- GSList *tmp = clist->next;
- GParamSpec *pspec = clist->data;
- GValue *value = g_new (GValue, 1);
+ object = g_object_newv (object_type, n_params, params);
- value->g_type = 0;
- g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- g_param_value_set_default (pspec, value);
-
- if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
- cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
- cparams[n_cparams].pspec = pspec;
- cparams[n_cparams].value = value;
- n_cparams++;
-
- g_slist_free_1 (clist);
- clist = tmp;
- }
- object = class->constructor (object_type, n_cparams, cparams);
-
- /* free construction values */
- while (n_cparams--)
- {
- g_value_unset (cparams[n_cparams].value);
- g_free (cparams[n_cparams].value);
- }
- g_free (cparams);
-
- /* release g_object_init() notification queue freeze_count */
- nqueue = object_freeze_notifies (object);
- nqueue->freeze_count--;
-
- /* set remaining properties */
- cparams = nparams;
- while (n_nparams--)
- {
- GValue *value = nparams->value;
- GParamSpec *pspec = nparams->pspec;
-
- nparams++;
- object_set_property (object, pspec, value, nqueue);
- g_value_unset (value);
- g_free (value);
- }
- g_free (cparams);
+ while (n_params--)
+ g_value_unset (¶ms[n_params].value);
+ g_free (params);
g_type_class_unref (class);
- /* release our own freeze count and handle notifications */
- object_thaw_notifies (object, nqueue);
-
return object;
}
@@ -853,7 +784,7 @@ g_object_constructor (GType type,
/* set construction parameters */
if (n_construct_properties)
{
- NotifyQueue *nqueue = object_freeze_notifies (object);
+ GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
/* set construct properties */
while (n_construct_properties--)
@@ -864,9 +795,9 @@ g_object_constructor (GType type,
construct_params++;
object_set_property (object, pspec, value, nqueue);
}
- nqueue->freeze_count--;
+ g_object_notify_queue_thaw (object, nqueue);
/* the notification queue is still frozen from g_object_init(), so
- * we don't need to handle it here, g_object_new_valist() takes
+ * we don't need to handle it here, g_object_newv() takes
* care of that
*/
}
@@ -879,13 +810,13 @@ g_object_set_valist (GObject *object,
const gchar *first_property_name,
va_list var_args)
{
- NotifyQueue *nqueue;
+ GObjectNotifyQueue *nqueue;
const gchar *name;
g_return_if_fail (G_IS_OBJECT (object));
g_object_ref (object);
- nqueue = object_freeze_notifies (object);
+ nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
name = first_property_name;
while (name)
@@ -935,7 +866,7 @@ g_object_set_valist (GObject *object,
name = va_arg (var_args, gchar*);
}
- object_thaw_notifies (object, nqueue);
+ g_object_notify_queue_thaw (object, nqueue);
g_object_unref (object);
}
@@ -1037,7 +968,7 @@ g_object_set_property (GObject *object,
const gchar *property_name,
const GValue *value)
{
- NotifyQueue *nqueue;
+ GObjectNotifyQueue *nqueue;
GParamSpec *pspec;
g_return_if_fail (G_IS_OBJECT (object));
@@ -1045,7 +976,7 @@ g_object_set_property (GObject *object,
g_return_if_fail (G_IS_VALUE (value));
g_object_ref (object);
- nqueue = object_freeze_notifies (object);
+ nqueue = g_object_notify_queue_freeze (object, &property_notify_context);
pspec = g_param_spec_pool_lookup (pspec_pool,
property_name,
@@ -1059,7 +990,7 @@ g_object_set_property (GObject *object,
else
object_set_property (object, pspec, value, nqueue);
- object_thaw_notifies (object, nqueue);
+ g_object_notify_queue_thaw (object, nqueue);
g_object_unref (object);
}
diff --git a/gobject/gobject.h b/gobject/gobject.h
index 87f4de8fe..d46d5cefa 100644
--- a/gobject/gobject.h
+++ b/gobject/gobject.h
@@ -65,9 +65,7 @@ struct _GObjectClass
{
GTypeClass g_type_class;
- /* private, these fields might vanish */
- guint n_property_specs;
- GParamSpec **property_specs;
+ /*< private >*/
GSList *construct_properties;
/* public overridable methods */
@@ -85,22 +83,19 @@ struct _GObjectClass
void (*shutdown) (GObject *object);
void (*finalize) (GObject *object);
- /*< private >*/
+ /* seldomly overidden */
void (*dispatch_properties_changed) (GObject *object,
guint n_pspecs,
GParamSpec **pspecs);
/* signals */
- void (*properties_changed) (GObject *object,
- guint n_pspecs,
- GParamSpec **pspecs);
void (*notify) (GObject *object,
GParamSpec *pspec);
};
struct _GObjectConstructParam
{
- GParamSpec *pspec;
- GValue *value;
+ GParamSpec *pspec;
+ GValue *value;
};
@@ -110,9 +105,14 @@ void g_object_class_install_property (GObjectClass *oclass,
GParamSpec *pspec);
GParamSpec* g_object_class_find_property (GObjectClass *oclass,
const gchar *property_name);
+GParamSpec**g_object_class_list_properties (GObjectClass *oclass,
+ guint *n_properties);
gpointer g_object_new (GType object_type,
const gchar *first_property_name,
...);
+gpointer g_object_newv (GType object_type,
+ guint n_parameters,
+ GParameter *parameters);
gpointer g_object_new_valist (GType object_type,
const gchar *first_property_name,
va_list var_args);
@@ -189,18 +189,21 @@ guint g_signal_connect_object (gpointer instance,
/* --- implementation macros --- */
-#define G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec) \
+#define G_OBJECT_WARN_INVALID_PSPEC(object, pname, property_id, pspec) \
G_STMT_START { \
GObject *_object = (GObject*) (object); \
GParamSpec *_pspec = (GParamSpec*) (pspec); \
guint _property_id = (property_id); \
- g_warning ("%s: invalid property id %u for \"%s\" of type `%s' in `%s'", \
+ g_warning ("%s: invalid %s id %u for \"%s\" of type `%s' in `%s'", \
G_STRLOC, \
+ (pname), \
_property_id, \
_pspec->name, \
g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \
G_OBJECT_TYPE_NAME (_object)); \
} G_STMT_END
+#define G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec) \
+ G_OBJECT_WARN_INVALID_PSPEC ((object), "property id", (property_id), (pspec))
G_END_DECLS
diff --git a/gobject/gobjectnotifyqueue.c b/gobject/gobjectnotifyqueue.c
new file mode 100644
index 000000000..d51028131
--- /dev/null
+++ b/gobject/gobjectnotifyqueue.c
@@ -0,0 +1,161 @@
+/* GObject - GLib Type, Object, Parameter and Signal Library
+ * Copyright (C) 1998-1999, 2000-2001 Tim Janik and Red Hat, Inc.
+ *
+ * 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_NOTIFY_H__
+#define __G_NOTIFY_H__
+
+#include
+
+G_BEGIN_DECLS
+
+
+/* --- typedefs --- */
+typedef struct _GObjectNotifyContext GObjectNotifyContext;
+typedef struct _GObjectNotifyQueue GObjectNotifyQueue;
+typedef void (*GObjectNotifyQueueDispatcher) (GObject *object,
+ guint n_pspecs,
+ GParamSpec **pspecs);
+
+
+/* --- structures --- */
+struct _GObjectNotifyContext
+{
+ GQuark quark_notify_queue;
+ GObjectNotifyQueueDispatcher dispatcher;
+ GTrashStack *nqueue_trash;
+};
+struct _GObjectNotifyQueue
+{
+ GObjectNotifyContext *context;
+ GSList *pspecs;
+ guint n_pspecs;
+ guint freeze_count;
+};
+
+
+/* --- functions --- */
+static void
+g_object_notify_queue_free (gpointer data)
+{
+ GObjectNotifyQueue *nqueue = data;
+
+ g_slist_free (nqueue->pspecs);
+ g_trash_stack_push (&nqueue->context->nqueue_trash, nqueue);
+}
+
+static inline GObjectNotifyQueue*
+g_object_notify_queue_freeze (GObject *object,
+ GObjectNotifyContext *context)
+{
+ GObjectNotifyQueue *nqueue;
+
+ nqueue = g_datalist_id_get_data (&object->qdata, context->quark_notify_queue);
+ if (!nqueue)
+ {
+ nqueue = g_trash_stack_pop (&context->nqueue_trash);
+ if (!nqueue)
+ {
+ guint i;
+
+ nqueue = g_new (GObjectNotifyQueue, 16);
+ for (i = 0; i < 15; i++)
+ g_trash_stack_push (&context->nqueue_trash, nqueue++);
+ }
+ memset (nqueue, 0, sizeof (*nqueue));
+ nqueue->context = context;
+ g_datalist_id_set_data_full (&object->qdata, context->quark_notify_queue,
+ nqueue, g_object_notify_queue_free);
+ }
+ nqueue->freeze_count++;
+
+ return nqueue;
+}
+
+static inline void
+g_object_notify_queue_thaw (GObject *object,
+ GObjectNotifyQueue *nqueue)
+{
+ GObjectNotifyContext *context = nqueue->context;
+ GParamSpec *pspecs_mem[16], **pspecs, **free_me = NULL;
+ GSList *slist;
+ guint n_pspecs = 0;
+
+ g_return_if_fail (nqueue->freeze_count > 0);
+
+ nqueue->freeze_count--;
+ if (nqueue->freeze_count)
+ return;
+ g_return_if_fail (object->ref_count > 0);
+
+ pspecs = nqueue->n_pspecs > 16 ? free_me = g_new (GParamSpec*, nqueue->n_pspecs) : pspecs_mem;
+ for (slist = nqueue->pspecs; slist; slist = slist->next)
+ {
+ GParamSpec *pspec = slist->data;
+ gint i = 0;
+
+ /* dedup, make pspecs in the list unique */
+ redo_dedup_check:
+ if (pspecs[i] == pspec)
+ continue;
+ if (++i < n_pspecs)
+ goto redo_dedup_check;
+
+ pspecs[n_pspecs++] = pspec;
+ }
+ g_datalist_id_set_data (&object->qdata, context->quark_notify_queue, NULL);
+
+ if (n_pspecs)
+ context->dispatcher (object, n_pspecs, pspecs);
+ g_free (free_me);
+}
+
+static inline void
+g_object_notify_queue_clear (GObject *object,
+ GObjectNotifyQueue *nqueue)
+{
+ g_return_if_fail (nqueue->freeze_count > 0);
+
+ g_slist_free (nqueue->pspecs);
+ nqueue->pspecs = NULL;
+ nqueue->n_pspecs = 0;
+}
+
+static inline void
+g_object_notify_queue_add (GObject *object,
+ GObjectNotifyQueue *nqueue,
+ GParamSpec *pspec)
+{
+ if (pspec->flags & G_PARAM_READABLE)
+ {
+ /* we do the deduping in _thaw */
+ nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec);
+ nqueue->n_pspecs++;
+ }
+}
+
+static inline GObjectNotifyQueue*
+g_object_notify_queue_from_object (GObject *object,
+ GObjectNotifyContext *context)
+{
+ return g_datalist_id_get_data (&object->qdata, context->quark_notify_queue);
+}
+
+
+G_END_DECLS
+
+#endif /* __G_OBJECT_H__ */
diff --git a/gobject/gparam.c b/gobject/gparam.c
index 511717763..4fbf45588 100644
--- a/gobject/gparam.c
+++ b/gobject/gparam.c
@@ -144,6 +144,7 @@ g_param_spec_init (GParamSpec *pspec,
pspec->owner_type = 0;
pspec->qdata = NULL;
pspec->ref_count = 1;
+ pspec->param_id = 0;
g_datalist_id_set_data (&pspec->qdata, quark_floating, GUINT_TO_POINTER (TRUE));
}
@@ -725,8 +726,8 @@ pool_list (gpointer key,
}
GList*
-g_param_spec_pool_list (GParamSpecPool *pool,
- GType owner_type)
+g_param_spec_pool_belongings (GParamSpecPool *pool,
+ GType owner_type)
{
gpointer data[2];
@@ -742,6 +743,99 @@ g_param_spec_pool_list (GParamSpecPool *pool,
return data[0];
}
+static gint
+pspec_compare_id (gconstpointer a,
+ gconstpointer b)
+{
+ const GParamSpec *pspec1 = a, *pspec2 = b;
+
+ return pspec1->param_id < pspec2->param_id ? -1 : pspec1->param_id > pspec2->param_id;
+}
+
+static inline GSList*
+pspec_list_remove_overridden (GSList *plist,
+ GHashTable *ht,
+ GType owner_type,
+ guint *n_p)
+{
+ GSList *rlist = NULL;
+
+ while (plist)
+ {
+ GSList *tmp = plist->next;
+ GParamSpec *pspec = plist->data;
+
+ if (param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE) != pspec)
+ g_slist_free_1 (plist);
+ else
+ {
+ plist->next = rlist;
+ rlist = plist;
+ *n_p += 1;
+ }
+ plist = tmp;
+ }
+ return rlist;
+}
+
+static void
+pool_depth_list (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GParamSpec *pspec = value;
+ gpointer *data = user_data;
+ GSList **slists = data[0];
+ GType owner_type = GPOINTER_TO_UINT (data[1]);
+
+ if (g_type_is_a (owner_type, pspec->owner_type))
+ {
+ guint d = g_type_depth (pspec->owner_type);
+
+ slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
+ }
+}
+
+GParamSpec** /* free result */
+g_param_spec_pool_list (GParamSpecPool *pool,
+ GType owner_type,
+ guint *n_pspecs_p)
+{
+ GParamSpec **pspecs, **p;
+ GSList **slists, *node;
+ gpointer data[2];
+ guint d, i;
+
+ g_return_val_if_fail (pool != NULL, NULL);
+ g_return_val_if_fail (owner_type > 0, NULL);
+ g_return_val_if_fail (n_pspecs_p != NULL, NULL);
+
+ G_SLOCK (&pool->smutex);
+ *n_pspecs_p = 0;
+ d = g_type_depth (owner_type);
+ slists = g_new0 (GSList*, d);
+ data[0] = slists;
+ data[1] = GUINT_TO_POINTER (owner_type);
+ g_hash_table_foreach (pool->hash_table, pool_depth_list, &data);
+ for (i = 0; i < d - 1; i++)
+ slists[i] = pspec_list_remove_overridden (slists[i], pool->hash_table, owner_type, n_pspecs_p);
+ *n_pspecs_p += g_slist_length (slists[i]);
+ pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
+ p = pspecs;
+ for (i = 0; i < d; i++)
+ {
+ slists[i] = g_slist_sort (slists[i], pspec_compare_id);
+ for (node = slists[i]; node; node = node->next)
+ *p++ = node->data;
+ g_slist_free (slists[i]);
+ }
+ *p++ = NULL;
+ g_free (slists);
+ G_SUNLOCK (&pool->smutex);
+
+ return pspecs;
+}
+
/* --- auxillary functions --- */
typedef struct
diff --git a/gobject/gparam.h b/gobject/gparam.h
index 744a3978a..7def6d278 100644
--- a/gobject/gparam.h
+++ b/gobject/gparam.h
@@ -56,6 +56,7 @@ typedef enum
/* --- typedefs & structures --- */
typedef struct _GParamSpec GParamSpec;
typedef struct _GParamSpecClass GParamSpecClass;
+typedef struct _GParameter GParameter;
typedef struct _GParamSpecPool GParamSpecPool;
struct _GParamSpec
{
@@ -66,11 +67,12 @@ struct _GParamSpec
gchar *blurb;
GParamFlags flags;
GType value_type;
+ GType owner_type; /* class using this property */
/*< private >*/
- GType owner_type;
GData *qdata;
guint ref_count;
+ guint param_id; /* sort-criteria */
};
struct _GParamSpecClass
{
@@ -89,6 +91,11 @@ struct _GParamSpecClass
const GValue *value1,
const GValue *value2);
};
+struct _GParameter /* auxillary structure for _setv() variants */
+{
+ const gchar *name;
+ GValue value;
+};
/* --- prototypes --- */
@@ -165,8 +172,11 @@ GParamSpec* g_param_spec_pool_lookup (GParamSpecPool *pool,
const gchar *param_name,
GType owner_type,
gboolean walk_ancestors);
-GList* g_param_spec_pool_list (GParamSpecPool *pool,
+GList* g_param_spec_pool_belongings (GParamSpecPool *pool,
GType owner_type);
+GParamSpec** g_param_spec_pool_list (GParamSpecPool *pool,
+ GType owner_type,
+ guint *n_pspecs_p);
diff --git a/gobject/gsignal.h b/gobject/gsignal.h
index ddcae8037..2ba7a0bd2 100644
--- a/gobject/gsignal.h
+++ b/gobject/gsignal.h
@@ -222,6 +222,10 @@ guint g_signal_handlers_disconnect_matched (gpointer instance,
/* --- convenience --- */
#define g_signal_connectc(instance, detailed_signal, c_handler, data, swapped) \
g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (swapped), FALSE)
+#define g_signal_connect(instance, detailed_signal, c_handler, data) \
+ g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, FALSE, FALSE)
+#define g_signal_connect_swapped(instance, detailed_signal, c_handler, data) \
+ g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, TRUE, FALSE)
#define g_signal_disconnect_by_func(instance, func, data) \
g_signal_handlers_disconnect_matched ((instance), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, \
0, 0, NULL, (func), (data))
diff --git a/gobject/gtype.c b/gobject/gtype.c
index 590598c57..664580be3 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -2073,6 +2073,18 @@ g_type_parent (GType type)
return node ? NODE_PARENT_TYPE (node) : 0;
}
+guint
+g_type_depth (GType type)
+{
+ TypeNode *node;
+
+ G_READ_LOCK (&type_rw_lock);
+ node = lookup_type_node_L (type);
+ G_READ_UNLOCK (&type_rw_lock);
+
+ return node ? node->n_supers + 1 : 0;
+}
+
GType
g_type_next_base (GType type,
GType base_type)
diff --git a/gobject/gtype.h b/gobject/gtype.h
index 2c9ed2d57..2bdb5c295 100644
--- a/gobject/gtype.h
+++ b/gobject/gtype.h
@@ -187,6 +187,7 @@ G_CONST_RETURN gchar* g_type_name (GType type);
GQuark g_type_qname (GType type);
GType g_type_from_name (const gchar *name);
GType g_type_parent (GType type);
+guint g_type_depth (GType type);
GType g_type_next_base (GType leaf_type,
GType root_type);
gboolean g_type_is_a (GType type,