diff options
author | James Henstridge <james@daa.com.au> | 2001-12-14 09:06:09 +0000 |
---|---|---|
committer | James Henstridge <jamesh@src.gnome.org> | 2001-12-14 09:06:09 +0000 |
commit | 5e3a4eb1c77121f9db6305aaa3456115255c12db (patch) | |
tree | 7328944933f7146b104179d44d1f63fdcbb1834b | |
parent | f2853162d7cd949136f6055afbcf41daa7b03bcf (diff) | |
download | pygobject-5e3a4eb1c77121f9db6305aaa3456115255c12db.tar.gz pygobject-5e3a4eb1c77121f9db6305aaa3456115255c12db.tar.xz pygobject-5e3a4eb1c77121f9db6305aaa3456115255c12db.zip |
use __gsignals__ notation here.
2001-12-14 James Henstridge <james@daa.com.au>
* examples/gobject/signal.py: use __gsignals__ notation here.
* gobjectmodule.c (create_signal, add_signals): helper routines
for handling __gsignals__ attribute of classes.
(pyg_type_register): add support for creating signals as part of
type registration.
-rw-r--r-- | examples/signal.py | 7 | ||||
-rw-r--r-- | gobject/gobjectmodule.c | 106 |
2 files changed, 109 insertions, 4 deletions
diff --git a/examples/signal.py b/examples/signal.py index c52f0ad..3d72e75 100644 --- a/examples/signal.py +++ b/examples/signal.py @@ -1,14 +1,15 @@ import gobject class C(gobject.GObject): + __gsignals__ = { + 'my_signal': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + (gobject.TYPE_INT,)) + } def __init__(self): self.__gobject_init__() # default constructor using our new GType def do_my_signal(self, arg): print "C: class closure for `my_signal' called with argument", arg - gobject.type_register(C) -gobject.signal_new("my_signal", C, gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, (gobject.TYPE_INT, )) class D(C): def do_my_signal(self, arg): diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c index d76f353..fc6ccfa 100644 --- a/gobject/gobjectmodule.c +++ b/gobject/gobjectmodule.c @@ -1928,10 +1928,94 @@ pyg_object_class_init(GObjectClass *class, PyObject *py_class) G_OBJECT_CLASS_NAME(class), py_class); } +static gboolean +create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple) +{ + GSignalFlags signal_flags; + PyObject *py_return_type, *py_param_types; + GType return_type; + guint n_params, i; + GType *param_types; + guint signal_id; + + if (!PyArg_ParseTuple(tuple, "iOO", &signal_flags, &py_return_type, + &py_param_types)) { + gchar buf[128]; + + PyErr_Clear(); + g_snprintf(buf, sizeof(buf), "value for __gsignals__['%s'] not in correct format", signal_name); + PyErr_SetString(PyExc_TypeError, buf); + return FALSE; + } + + return_type = pyg_type_from_object(py_return_type); + if (!return_type) + return FALSE; + if (!PySequence_Check(py_param_types)) { + gchar buf[128]; + + g_snprintf(buf, sizeof(buf), "third element of __gsignals__['%s'] tuple must be a sequence", signal_name); + PyErr_SetString(PyExc_TypeError, buf); + return FALSE; + } + n_params = PySequence_Length(py_param_types); + param_types = g_new(GType, n_params); + for (i = 0; i < n_params; i++) { + PyObject *item = PySequence_GetItem(py_param_types, i); + + param_types[i] = pyg_type_from_object(item); + if (param_types[i] == 0) { + Py_DECREF(item); + g_free(param_types); + return FALSE; + } + Py_DECREF(item); + } + + signal_id = g_signal_newv(signal_name, instance_type, signal_flags, + pyg_signal_class_closure_get(), + (GSignalAccumulator)0, NULL, + (GSignalCMarshaller)0, + return_type, n_params, param_types); + g_free(param_types); + + if (signal_id == 0) { + gchar buf[128]; + + g_snprintf(buf, sizeof(buf), "could not create signal for %s", + signal_name); + PyErr_SetString(PyExc_RuntimeError, buf); + return FALSE; + } + return TRUE; +} + +static gboolean +add_signals (PyTypeObject *class, GType instance_type, PyObject *signals) +{ + int pos = 0; + PyObject *key, *value; + + while (PyDict_Next(signals, &pos, &key, &value)) { + const gchar *signal_name; + + if (!PyString_Check(key)) { + PyErr_SetString(PyExc_TypeError, + "__gsignals__ keys must be strings"); + return FALSE; + } + signal_name = PyString_AsString (key); + + if (!create_signal(instance_type, signal_name, value)) + return FALSE; + } + return TRUE; +} + static PyObject * pyg_type_register(PyObject *self, PyObject *args) { - PyObject *gtype, *module; + PyObject *gtype, *module, *gsignals; PyTypeObject *class; GType parent_type, instance_type; gchar *type_name = NULL; @@ -2008,6 +2092,26 @@ pyg_type_register(PyObject *self, PyObject *args) PyDict_SetItemString(class->tp_dict, "__gtype__", gtype); Py_DECREF(gtype); + /* we look this up in the instance dictionary, so we don't + * accidentally get a parent type's __gsignals__ attribute. */ + gsignals = PyDict_GetItemString(class->tp_dict, "__gsignals__"); + if (gsignals) { + if (!PyDict_Check(gsignals)) { + PyErr_SetString(PyExc_TypeError, + "__gsignals__ attribute not a dict!"); + Py_DECREF(gsignals); + return NULL; + } + if (!add_signals(class, instance_type, gsignals)) { + Py_DECREF(gsignals); + return NULL; + } + PyDict_DelItemString(class->tp_dict, "__gsignals__"); + Py_DECREF(gsignals); + } else { + PyErr_Clear(); + } + Py_INCREF(Py_None); return Py_None; } |