diff options
-rw-r--r-- | gobject/gobjectmodule.c | 95 |
1 files changed, 88 insertions, 7 deletions
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index e965379..77e434f 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -1629,6 +1629,81 @@ pygobject_stop_emission(PyGObject *self, PyObject *args) return Py_None; } +static PyObject * +pygobject_chain_from_overridden(PyGObject *self, PyObject *args) +{ + guint signal_id, i, len; + PyObject *first, *py_ret; + gchar *name; + GSignalQuery query; + GValue *params, ret = { 0, }; + + len = PyTuple_Size(args); + if (len < 1) { + PyErr_SetString(PyExc_TypeError,"GObject.chain_from_overridden needs at least one arg"); + return NULL; + } + first = PySequence_GetSlice(args, 0, 1); + if (!PyArg_ParseTuple(first, "s:GObject.emit", &name)) { + Py_DECREF(first); + return NULL; + } + Py_DECREF(first); + signal_id = g_signal_lookup(name, G_OBJECT_TYPE(self->obj)); + if (signal_id == 0) { + PyErr_SetString(PyExc_TypeError, "unknown signal name"); + return NULL; + } + g_signal_query(signal_id, &query); + if (len != query.n_params + 1) { + gchar buf[128]; + + g_snprintf(buf, sizeof(buf), + "%d parameters needed for signal %s; %d given", + query.n_params, name, len - 1); + PyErr_SetString(PyExc_TypeError, buf); + return NULL; + } + params = g_new0(GValue, query.n_params + 1); + g_value_init(¶ms[0], G_OBJECT_TYPE(self->obj)); + g_value_set_object(¶ms[0], G_OBJECT(self->obj)); + + for (i = 0; i < query.n_params; i++) + g_value_init(¶ms[i + 1], + query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE); + for (i = 0; i < query.n_params; i++) { + PyObject *item = PyTuple_GetItem(args, i+1); + + if (pyg_value_from_pyobject(¶ms[i+1], item) < 0) { + gchar buf[128]; + + g_snprintf(buf, sizeof(buf), + "could not convert type %s to %s required for parameter %d", + item->ob_type->tp_name, + g_type_name(G_VALUE_TYPE(¶ms[i+1])), i); + PyErr_SetString(PyExc_TypeError, buf); + for (i = 0; i < query.n_params + 1; i++) + g_value_unset(¶ms[i]); + g_free(params); + return NULL; + } + } + if (query.return_type != G_TYPE_NONE) + g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); + g_signal_chain_from_overridden(params, signal_id, &ret); + for (i = 0; i < query.n_params + 1; i++) + g_value_unset(¶ms[i]); + g_free(params); + if (query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE != G_TYPE_NONE) { + py_ret = pyg_value_as_pyobject(&ret); + g_value_unset(&ret); + } else { + Py_INCREF(Py_None); + py_ret = Py_None; + } + return py_ret; +} + static PyMethodDef pygobject_methods[] = { { "__gobject_init__", (PyCFunction)pygobject__gobject_init__, METH_VARARGS|METH_KEYWORDS }, @@ -1650,6 +1725,7 @@ static PyMethodDef pygobject_methods[] = { { "emit", (PyCFunction)pygobject_emit, METH_VARARGS }, { "stop_emission", (PyCFunction)pygobject_stop_emission, METH_VARARGS }, { "emit_stop_by_name", (PyCFunction)pygobject_stop_emission,METH_VARARGS }, + { "chain_from_overridden", (PyCFunction)pygobject_chain_from_overridden,METH_VARARGS }, { NULL, NULL, 0 } }; @@ -1993,12 +2069,9 @@ create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple) static gboolean override_signal(GType instance_type, const gchar *signal_name) { - GObjectClass *oclass; guint signal_id; - oclass = g_type_class_ref(instance_type); signal_id = g_signal_lookup(signal_name, instance_type); - g_type_class_unref(oclass); if (!signal_id) { gchar buf[128]; @@ -2014,15 +2087,19 @@ override_signal(GType instance_type, const gchar *signal_name) static gboolean add_signals (GType instance_type, PyObject *signals) { + GObjectClass *oclass; int pos = 0; PyObject *key, *value; + oclass = g_type_class_ref(instance_type); while (PyDict_Next(signals, &pos, &key, &value)) { const gchar *signal_name; + gboolean retval = TRUE; if (!PyString_Check(key)) { PyErr_SetString(PyExc_TypeError, "__gsignals__ keys must be strings"); + g_type_class_unref(oclass); return FALSE; } signal_name = PyString_AsString (key); @@ -2030,13 +2107,17 @@ add_signals (GType instance_type, PyObject *signals) if (value == Py_None || (PyString_Check(value) && !strcmp(PyString_AsString(value), "override"))) { - if (!override_signal(instance_type, signal_name)) - return FALSE; + retval = override_signal(instance_type, signal_name); } else { - if (!create_signal(instance_type, signal_name, value)) - return FALSE; + retval = create_signal(instance_type, signal_name, value); + } + + if (!retval) { + g_type_class_unref(oclass); + return FALSE; } } + g_type_class_unref(oclass); return TRUE; } |