aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside/qsignal.cpp
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2010-05-13 15:50:42 -0300
committerRenato Filho <renato.filho@openbossa.org>2010-05-17 19:53:54 -0300
commitc5fd4d4830cb49c9f8087d7e54335f4c248f76bf (patch)
tree6a4fd6a9e30f1d5a1b3ead182d768d2f4fc38a79 /libpyside/qsignal.cpp
parentd2a6f35ef914b000ddd7685925075985c76817ac (diff)
Implemented support to modify slot return type.
Included method type in DynamicQMetaObject metadata. Moved Signal/Slot objet to libpyside. Create unittest to signal class. Implemented disconnection function. Fixed emit method on signal object
Diffstat (limited to 'libpyside/qsignal.cpp')
-rw-r--r--libpyside/qsignal.cpp413
1 files changed, 413 insertions, 0 deletions
diff --git a/libpyside/qsignal.cpp b/libpyside/qsignal.cpp
new file mode 100644
index 000000000..8fe79ee1e
--- /dev/null
+++ b/libpyside/qsignal.cpp
@@ -0,0 +1,413 @@
+#define protected public
+
+#include <shiboken.h>
+#include <Python.h>
+#include <QDebug>
+
+#include "qsignal.h"
+#include "signalmanager.h"
+
+#define SIGNAL_CLASS_NAME "Signal"
+
+namespace PySide
+{
+
+extern "C"
+{
+
+static int qsignal_init(PyObject*, PyObject*, PyObject*);
+static void qsignal_free(void*);
+static void qsignal_instance_free(void*);
+
+//methods
+static PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kw);
+static PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args);
+static PyObject* qsignal_instance_emit(PyObject *self, PyObject *args);
+
+//aux
+static char* qsignal_build_signature(const char *name, const char *signature);
+static const char* qsignal_get_type_name(PyObject *type);
+static void qsignal_append_signature(SignalData *self, PyObject *args);
+static void qsignal_instance_initialize(PyObject *instance, SignalData *data, PyObject *source);
+
+PyTypeObject PySideSignal_Type = {
+ PyObject_HEAD_INIT(0)
+ 0, /*ob_size*/
+ SIGNAL_CLASS_NAME, /*tp_name*/
+ sizeof(SignalData), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ SIGNAL_CLASS_NAME, /*tp_doc */
+ 0, /*tp_traverse */
+ 0, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ 0, /*tp_iter */
+ 0, /*tp_iternext */
+ 0, /*tp_methods */
+ 0, /*tp_members */
+ 0, /*tp_getset */
+ 0, /*tp_base */
+ 0, /*tp_dict */
+ 0, /*tp_descr_get */
+ 0, /*tp_descr_set */
+ 0, /*tp_dictoffset */
+ (initproc)qsignal_init, /*tp_init */
+ 0, /*tp_alloc */
+ PyType_GenericNew, /*tp_new */
+ qsignal_free, /*tp_free */
+ 0, /*tp_is_gc */
+ 0, /*tp_bases */
+ 0, /*tp_mro */
+ 0, /*tp_cache */
+ 0, /*tp_subclasses */
+ 0, /*tp_weaklist */
+ 0, /*tp_del */
+};
+
+static PyMethodDef PySideQtSignalInstance_methods[] = {
+ {"connect", (PyCFunction)qsignal_instance_connect, METH_VARARGS|METH_KEYWORDS},
+ {"disconnect", (PyCFunction)qsignal_instance_disconnect, METH_VARARGS},
+ {"emit", (PyCFunction)qsignal_instance_emit, METH_VARARGS},
+ {NULL} /* Sentinel */
+};
+
+PyTypeObject PySideSignalInstance_Type = {
+ PyObject_HEAD_INIT(0)
+ 0, /*ob_size*/
+ SIGNAL_CLASS_NAME, /*tp_name*/
+ sizeof(SignalData), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+ SIGNAL_CLASS_NAME"I", /*tp_doc */
+ 0, /*tp_traverse */
+ 0, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ 0, /*tp_iter */
+ 0, /*tp_iternext */
+ PySideQtSignalInstance_methods, /*tp_methods */
+ 0, /*tp_members */
+ 0, /*tp_getset */
+ &PySideSignal_Type, /*tp_base */
+ 0, /*tp_dict */
+ 0, /*tp_descr_get */
+ 0, /*tp_descr_set */
+ 0, /*tp_dictoffset */
+ 0, /*tp_init */
+ 0, /*tp_alloc */
+ PyType_GenericNew, /*tp_new */
+ qsignal_instance_free, /*tp_free */
+ 0, /*tp_is_gc */
+ 0, /*tp_bases */
+ 0, /*tp_mro */
+ 0, /*tp_cache */
+ 0, /*tp_subclasses */
+ 0, /*tp_weaklist */
+ 0, /*tp_del */
+};
+
+
+PyAPI_FUNC(void) init_signal(PyObject* module)
+{
+ if (PyType_Ready(&PySideSignal_Type) < 0)
+ return;
+
+ Py_INCREF(&PySideSignal_Type);
+ PyModule_AddObject(module, SIGNAL_CLASS_NAME, ((PyObject*)&PySideSignal_Type));
+
+ if (PyType_Ready(&PySideSignalInstance_Type) < 0)
+ return;
+
+ Py_INCREF(&PySideSignalInstance_Type);
+}
+
+
+} // extern "C"
+
+void signal_update_source(PyObject *source)
+{
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+ PyTypeObject *obType = source->ob_type;
+
+ while (PyDict_Next(obType->tp_dict, &pos, &key, &value)) {
+
+ if (value->ob_type == &PySideSignal_Type) {
+ PyObject *signal_instance = (PyObject*)PyObject_New(SignalData, &PySideSignalInstance_Type);
+
+ qsignal_instance_initialize(signal_instance, reinterpret_cast<SignalData*>(value), source);
+
+ PyObject_SetAttr(source, key, signal_instance);
+ Py_DECREF(signal_instance);
+
+ }
+
+ }
+}
+
+const char* qsignal_get_type_name(PyObject *type)
+{
+ if (PyType_Check(type)) {
+ //tp_name return the full name
+ Shiboken::AutoDecRef type_name(PyObject_GetAttrString(type, "__name__"));
+ return PyString_AS_STRING((PyObject*)type_name);
+ } else if (PyString_Check(type)) {
+ return PyString_AS_STRING(type);
+ }
+ return "";
+}
+
+char* qsignal_build_signature(const char *name, const char *signature)
+{
+ QString signal;
+ signal.sprintf("2%s(%s)", name, (signature ? signature : "()"));
+ return strdup(QMetaObject::normalizedSignature(signal.toAscii()));
+}
+
+void qsignal_append_signature(SignalData *self, PyObject *args)
+{
+ char *signature = 0;
+ for(Py_ssize_t i=0, i_max=PySequence_Size(args); i < i_max; i++) {
+ Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
+ const char *type_name = qsignal_get_type_name(arg);
+ if (strlen(type_name) > 0) {
+ if (signature) {
+ signature = strcat(signature, ",");
+ signature = strcat(signature, type_name);
+ } else {
+ signature = strdup(type_name);
+ }
+ }
+ }
+
+ self->signatures_size++;
+ if (self->signatures_size > 1) {
+ self->signatures = (char**) realloc(self->signatures, sizeof(char**) * self->signatures_size);
+ } else {
+ self->signatures = (char**) malloc(sizeof(char**));
+ }
+ self->signatures[self->signatures_size -1] = qsignal_build_signature(self->signal_name, signature);
+ printf("registred signature:[%d][%s]\n", self->signatures_size -1, self->signatures[self->signatures_size -1]);
+ free(signature);
+}
+
+int qsignal_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static PyObject *emptyTuple = 0;
+ static const char *kwlist[] = {"name", 0};
+ char* arg_name = 0;
+
+ if (emptyTuple == 0)
+ emptyTuple = PyTuple_New(0);
+
+ if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds,
+ "|s:QtCore."SIGNAL_CLASS_NAME, (char**) kwlist, &arg_name))
+ return 0;
+
+ bool tupled_args = false;
+ SignalData *data = reinterpret_cast<SignalData*>(self);
+ if (arg_name)
+ data->signal_name = strdup(arg_name);
+
+ for(Py_ssize_t i=0, i_max=PyTuple_Size(args); i < i_max; i++) {
+ PyObject *arg = PyTuple_GET_ITEM(args, i);
+ if (PySequence_Check(arg)) {
+ tupled_args = true;
+ qsignal_append_signature(data, arg);
+ }
+ }
+
+ if (!tupled_args)
+ qsignal_append_signature(data, args);
+
+
+ return 1;
+}
+
+void qsignal_free(void *self)
+{
+ PyObject *pySelf = reinterpret_cast<PyObject*>(self);
+ SignalData *data = reinterpret_cast<SignalData*>(self);
+
+ //keep the data to instance
+ if (!data->initialized)
+ qsignal_instance_free(self);
+
+ pySelf->ob_type->tp_free (self);
+}
+
+void qsignal_instance_free(void *self)
+{
+ PyObject *pySelf = reinterpret_cast<PyObject*>(self);
+ SignalData *data = reinterpret_cast<SignalData*>(self);
+ free(data->signatures[0]);
+ for(int i=1, i_max=data->signatures_size; i < i_max; i++) {
+ free(data->signatures[i]);
+ }
+ free(data->signatures);
+ free(data->signal_name);
+ data->initialized = false;
+
+ pySelf->ob_type->tp_free (self);
+}
+
+void qsignal_instance_initialize(PyObject *instance, SignalData *data, PyObject *source)
+{
+ SignalData *self = reinterpret_cast<SignalData*>(instance);
+ self->signal_name = data->signal_name;
+ self->signatures_size = data->signatures_size;
+ self->signatures = data->signatures;
+ self->initialized = true;
+ self->source = source;
+ data->initialized = true;
+}
+
+PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *slot;
+ PyObject *type;
+ static const char *kwlist[] = {"type", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "O|O:"SIGNAL_CLASS_NAME, (char**) kwlist, &slot, &type))
+ return 0;
+
+ SignalData *source = reinterpret_cast<SignalData*>(self);
+ Shiboken::AutoDecRef pyArgs(PyList_New(0));
+
+ bool match = false;
+ if (slot->ob_type == &PySideSignal_Type) {
+ SignalData *target = reinterpret_cast<SignalData*>(slot);
+ for(int s, s_max=source->signatures_size; s < s_max; s++) {
+ for(int t, t_max=target->signatures_size; t < t_max; t++) {
+ if (QMetaObject::checkConnectArgs(source->signatures[s], target->signatures[t])) {
+ PyList_Append(pyArgs, source->source);
+ Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[s]));
+ PyList_Append(pyArgs, source_signature);
+
+ PyList_Append(pyArgs, target->source);
+ Shiboken::AutoDecRef target_signature(PyString_FromString(source->signatures[s]));
+ PyList_Append(pyArgs, target_signature);
+ match = true;
+ break;
+ }
+ }
+ if (match) break;
+ }
+ } else {
+ //try the first signature
+ PyList_Append(pyArgs, source->source);
+ Shiboken::AutoDecRef signature(PyString_FromString(source->signatures[0]));
+ PyList_Append(pyArgs, signature);
+
+ PyList_Append(pyArgs, slot);
+ match = true;
+ }
+
+ if (match) {
+ Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "connect"));
+ return PyObject_CallObject(pyMethod, tupleArgs);
+ }
+
+ return 0;
+}
+
+PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args)
+{
+ SignalData *source = reinterpret_cast<SignalData*>(self);
+ Shiboken::AutoDecRef pyArgs(PyList_New(0));
+
+ PyObject *slot;
+ if PyTuple_Check(args)
+ slot = PyTuple_GET_ITEM(args, 0);
+ else
+ slot = args;
+
+ bool match = false;
+ if (slot->ob_type == &PySideSignal_Type) {
+ SignalData *target = reinterpret_cast<SignalData*>(slot);
+ for(int s, s_max=source->signatures_size; s < s_max; s++) {
+ for(int t, t_max=target->signatures_size; t < t_max; t++) {
+ if (QMetaObject::checkConnectArgs(source->signatures[s], target->signatures[t])) {
+ PyList_Append(pyArgs, source->source);
+ Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[s]));
+ PyList_Append(pyArgs, source_signature);
+
+ PyList_Append(pyArgs, target->source);
+ Shiboken::AutoDecRef target_signature(PyString_FromString(source->signatures[s]));
+ PyList_Append(pyArgs, target_signature);
+ match = true;
+ break;
+ }
+ }
+ if (match) break;
+ }
+ } else {
+ //try the first signature
+ PyList_Append(pyArgs, source->source);
+ Shiboken::AutoDecRef signature(PyString_FromString(source->signatures[0]));
+ PyList_Append(pyArgs, signature);
+
+ PyList_Append(pyArgs, slot);
+ match = true;
+ }
+
+ if (match) {
+ Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "disconnect"));
+ return PyObject_CallObject(pyMethod, tupleArgs);
+ }
+
+ return 0;
+}
+
+PyObject* qsignal_instance_emit(PyObject *self, PyObject *args)
+{
+ SignalData *source = reinterpret_cast<SignalData*>(self);
+
+ Shiboken::AutoDecRef pyArgs(PyList_New(0));
+ Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[0]));
+
+ PyList_Append(pyArgs, source_signature);
+ for(Py_ssize_t i=0, i_max=PyTuple_Size(args); i < i_max; i++)
+ PyList_Append(pyArgs, PyTuple_GetItem(args, i));
+
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source->source, "emit"));
+
+ Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
+ return PyObject_CallObject(pyMethod, tupleArgs);
+}
+
+} //namespace PySide