Signal objects redirect calls for homonymous methods.
This commit is contained in:
parent
4b3b56acd7
commit
7fab5c03a9
4 changed files with 162 additions and 99 deletions
|
|
@ -52,6 +52,7 @@ struct SignalData {
|
||||||
char* signalName;
|
char* signalName;
|
||||||
char** signatures;
|
char** signatures;
|
||||||
int signaturesSize;
|
int signaturesSize;
|
||||||
|
PyObject* homonymousMethod;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int signalTpInit(PyObject*, PyObject*, PyObject*);
|
static int signalTpInit(PyObject*, PyObject*, PyObject*);
|
||||||
|
|
@ -64,54 +65,57 @@ static PyObject* signalInstanceDisconnect(PyObject*, PyObject*);
|
||||||
static PyObject* signalInstanceEmit(PyObject*, PyObject*);
|
static PyObject* signalInstanceEmit(PyObject*, PyObject*);
|
||||||
static PyObject* signalInstanceGetItem(PyObject*, PyObject*);
|
static PyObject* signalInstanceGetItem(PyObject*, PyObject*);
|
||||||
|
|
||||||
|
static PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw);
|
||||||
|
static PyObject* signalCall(PyObject*, PyObject*, PyObject*);
|
||||||
|
|
||||||
PyTypeObject PySideSignalType = {
|
PyTypeObject PySideSignalType = {
|
||||||
PyObject_HEAD_INIT(0)
|
PyObject_HEAD_INIT(0)
|
||||||
0, /*ob_size*/
|
/*ob_size*/ 0,
|
||||||
"PySide.QtCore."SIGNAL_CLASS_NAME, /*tp_name*/
|
/*tp_name*/ "PySide.QtCore."SIGNAL_CLASS_NAME,
|
||||||
sizeof(SignalData), /*tp_basicsize*/
|
/*tp_basicsize*/ sizeof(SignalData),
|
||||||
0, /*tp_itemsize*/
|
/*tp_itemsize*/ 0,
|
||||||
0, /*tp_dealloc*/
|
/*tp_dealloc*/ &Shiboken::deallocWrapper,
|
||||||
0, /*tp_print*/
|
/*tp_print*/ 0,
|
||||||
0, /*tp_getattr*/
|
/*tp_getattr*/ 0,
|
||||||
0, /*tp_setattr*/
|
/*tp_setattr*/ 0,
|
||||||
0, /*tp_compare*/
|
/*tp_compare*/ 0,
|
||||||
0, /*tp_repr*/
|
/*tp_repr*/ 0,
|
||||||
0, /*tp_as_number*/
|
/*tp_as_number*/ 0,
|
||||||
0, /*tp_as_sequence*/
|
/*tp_as_sequence*/ 0,
|
||||||
0, /*tp_as_mapping*/
|
/*tp_as_mapping*/ 0,
|
||||||
0, /*tp_hash */
|
/*tp_hash*/ 0,
|
||||||
0, /*tp_call*/
|
/*tp_call*/ signalCall,
|
||||||
0, /*tp_str*/
|
/*tp_str*/ 0,
|
||||||
0, /*tp_getattro*/
|
/*tp_getattro*/ 0,
|
||||||
0, /*tp_setattro*/
|
/*tp_setattro*/ 0,
|
||||||
0, /*tp_as_buffer*/
|
/*tp_as_buffer*/ 0,
|
||||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
|
||||||
SIGNAL_CLASS_NAME, /*tp_doc */
|
/*tp_doc*/ SIGNAL_CLASS_NAME,
|
||||||
0, /*tp_traverse */
|
/*tp_traverse*/ 0,
|
||||||
0, /*tp_clear */
|
/*tp_clear*/ 0,
|
||||||
0, /*tp_richcompare */
|
/*tp_richcompare*/ 0,
|
||||||
0, /*tp_weaklistoffset */
|
/*tp_weaklistoffset*/ 0,
|
||||||
0, /*tp_iter */
|
/*tp_iter*/ 0,
|
||||||
0, /*tp_iternext */
|
/*tp_iternext*/ 0,
|
||||||
0, /*tp_methods */
|
/*tp_methods*/ 0,
|
||||||
0, /*tp_members */
|
/*tp_members*/ 0,
|
||||||
0, /*tp_getset */
|
/*tp_getset*/ 0,
|
||||||
0, /*tp_base */
|
/*tp_base*/ 0,
|
||||||
0, /*tp_dict */
|
/*tp_dict*/ 0,
|
||||||
0, /*tp_descr_get */
|
/*tp_descr_get*/ 0,
|
||||||
0, /*tp_descr_set */
|
/*tp_descr_set*/ 0,
|
||||||
0, /*tp_dictoffset */
|
/*tp_dictoffset*/ 0,
|
||||||
signalTpInit, /*tp_init */
|
/*tp_init*/ signalTpInit,
|
||||||
0, /*tp_alloc */
|
/*tp_alloc*/ 0,
|
||||||
PyType_GenericNew, /*tp_new */
|
/*tp_new*/ PyType_GenericNew,
|
||||||
signalFree, /*tp_free */
|
/*tp_free*/ signalFree,
|
||||||
0, /*tp_is_gc */
|
/*tp_is_gc*/ 0,
|
||||||
0, /*tp_bases */
|
/*tp_bases*/ 0,
|
||||||
0, /*tp_mro */
|
/*tp_mro*/ 0,
|
||||||
0, /*tp_cache */
|
/*tp_cache*/ 0,
|
||||||
0, /*tp_subclasses */
|
/*tp_subclasses*/ 0,
|
||||||
0, /*tp_weaklist */
|
/*tp_weaklist*/ 0,
|
||||||
0, /*tp_del */
|
/*tp_del*/ 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static PyMethodDef SignalInstance_methods[] = {
|
static PyMethodDef SignalInstance_methods[] = {
|
||||||
|
|
@ -129,52 +133,52 @@ static PyMappingMethods SignalInstance_as_mapping = {
|
||||||
|
|
||||||
PyTypeObject PySideSignalInstanceType = {
|
PyTypeObject PySideSignalInstanceType = {
|
||||||
PyObject_HEAD_INIT(0)
|
PyObject_HEAD_INIT(0)
|
||||||
0, /*ob_size*/
|
/*ob_size*/ 0,
|
||||||
"PySide.QtCore."SIGNAL_CLASS_NAME, /*tp_name*/
|
/*tp_name*/ "PySide.QtCore."SIGNAL_CLASS_NAME,
|
||||||
sizeof(PySideSignalInstanceData),/*tp_basicsize*/
|
/*tp_basicsize*/ sizeof(PySideSignalInstanceData),
|
||||||
0, /*tp_itemsize*/
|
/*tp_itemsize*/ 0,
|
||||||
0, /*tp_dealloc*/
|
/*tp_dealloc*/ 0,
|
||||||
0, /*tp_print*/
|
/*tp_print*/ 0,
|
||||||
0, /*tp_getattr*/
|
/*tp_getattr*/ 0,
|
||||||
0, /*tp_setattr*/
|
/*tp_setattr*/ 0,
|
||||||
0, /*tp_compare*/
|
/*tp_compare*/ 0,
|
||||||
0, /*tp_repr*/
|
/*tp_repr*/ 0,
|
||||||
0, /*tp_as_number*/
|
/*tp_as_number*/ 0,
|
||||||
0, /*tp_as_sequence*/
|
/*tp_as_sequence*/ 0,
|
||||||
&SignalInstance_as_mapping,/*tp_as_mapping*/
|
/*tp_as_mapping*/ &SignalInstance_as_mapping,
|
||||||
0, /*tp_hash */
|
/*tp_hash*/ 0,
|
||||||
0, /*tp_call*/
|
/*tp_call*/ signalInstanceCall,
|
||||||
0, /*tp_str*/
|
/*tp_str*/ 0,
|
||||||
0, /*tp_getattro*/
|
/*tp_getattro*/ 0,
|
||||||
0, /*tp_setattro*/
|
/*tp_setattro*/ 0,
|
||||||
0, /*tp_as_buffer*/
|
/*tp_as_buffer*/ 0,
|
||||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
/*tp_flags*/ Py_TPFLAGS_DEFAULT,
|
||||||
SIGNAL_CLASS_NAME, /*tp_doc */
|
/*tp_doc*/ SIGNAL_CLASS_NAME,
|
||||||
0, /*tp_traverse */
|
/*tp_traverse*/ 0,
|
||||||
0, /*tp_clear */
|
/*tp_clear*/ 0,
|
||||||
0, /*tp_richcompare */
|
/*tp_richcompare*/ 0,
|
||||||
0, /*tp_weaklistoffset */
|
/*tp_weaklistoffset*/ 0,
|
||||||
0, /*tp_iter */
|
/*tp_iter*/ 0,
|
||||||
0, /*tp_iternext */
|
/*tp_iternext*/ 0,
|
||||||
SignalInstance_methods, /*tp_methods */
|
/*tp_methods*/ SignalInstance_methods,
|
||||||
0, /*tp_members */
|
/*tp_members*/ 0,
|
||||||
0, /*tp_getset */
|
/*tp_getset*/ 0,
|
||||||
0, /*tp_base */
|
/*tp_base*/ 0,
|
||||||
0, /*tp_dict */
|
/*tp_dict*/ 0,
|
||||||
0, /*tp_descr_get */
|
/*tp_descr_get*/ 0,
|
||||||
0, /*tp_descr_set */
|
/*tp_descr_set*/ 0,
|
||||||
0, /*tp_dictoffset */
|
/*tp_dictoffset*/ 0,
|
||||||
0, /*tp_init */
|
/*tp_init*/ 0,
|
||||||
0, /*tp_alloc */
|
/*tp_alloc*/ 0,
|
||||||
PyType_GenericNew, /*tp_new */
|
/*tp_new*/ PyType_GenericNew,
|
||||||
signalInstanceFree, /*tp_free */
|
/*tp_free*/ signalInstanceFree,
|
||||||
0, /*tp_is_gc */
|
/*tp_is_gc*/ 0,
|
||||||
0, /*tp_bases */
|
/*tp_bases*/ 0,
|
||||||
0, /*tp_mro */
|
/*tp_mro*/ 0,
|
||||||
0, /*tp_cache */
|
/*tp_cache*/ 0,
|
||||||
0, /*tp_subclasses */
|
/*tp_subclasses*/ 0,
|
||||||
0, /*tp_weaklist */
|
/*tp_weaklist*/ 0,
|
||||||
0, /*tp_del */
|
/*tp_del*/ 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
int signalTpInit(PyObject* self, PyObject* args, PyObject* kwds)
|
int signalTpInit(PyObject* self, PyObject* args, PyObject* kwds)
|
||||||
|
|
@ -224,6 +228,8 @@ void signalFree(void *self)
|
||||||
free(data->signalName);
|
free(data->signalName);
|
||||||
data->initialized = 0;
|
data->initialized = 0;
|
||||||
data->signaturesSize = 0;
|
data->signaturesSize = 0;
|
||||||
|
Py_XDECREF(data->homonymousMethod);
|
||||||
|
data->homonymousMethod = 0;
|
||||||
|
|
||||||
pySelf->ob_type->tp_base->tp_free(self);
|
pySelf->ob_type->tp_base->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
@ -236,8 +242,10 @@ void signalInstanceFree(void* self)
|
||||||
free(data->signalName);
|
free(data->signalName);
|
||||||
free(data->signature);
|
free(data->signature);
|
||||||
|
|
||||||
|
Py_XDECREF(data->homonymousMethod);
|
||||||
|
|
||||||
if (data->next) {
|
if (data->next) {
|
||||||
Py_XDECREF(data->next);
|
Py_DECREF(data->next);
|
||||||
data->next = 0;
|
data->next = 0;
|
||||||
}
|
}
|
||||||
pySelf->ob_type->tp_base->tp_free(self);
|
pySelf->ob_type->tp_base->tp_free(self);
|
||||||
|
|
@ -385,6 +393,38 @@ PyObject* signalInstanceDisconnect(PyObject* self, PyObject* args)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject* signalCall(PyObject* self, PyObject* args, PyObject* kw)
|
||||||
|
{
|
||||||
|
SignalData* signalData = reinterpret_cast<SignalData*>(self);
|
||||||
|
|
||||||
|
if (!signalData->homonymousMethod) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
descrgetfunc getDescriptor = signalData->homonymousMethod->ob_type->tp_descr_get;
|
||||||
|
Shiboken::AutoDecRef homonymousMethod(getDescriptor(signalData->homonymousMethod, 0, 0));
|
||||||
|
|
||||||
|
if (PyCFunction_GET_FLAGS(homonymousMethod.object()) & METH_STATIC)
|
||||||
|
return PyCFunction_Call(homonymousMethod, args, kw);
|
||||||
|
|
||||||
|
ternaryfunc callFunc = signalData->homonymousMethod->ob_type->tp_call;
|
||||||
|
return callFunc(homonymousMethod, args, kw);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw)
|
||||||
|
{
|
||||||
|
PySideSignalInstanceData* signalData = reinterpret_cast<PySideSignalInstanceData*>(self);
|
||||||
|
if (!signalData->homonymousMethod) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
descrgetfunc getDescriptor = signalData->homonymousMethod->ob_type->tp_descr_get;
|
||||||
|
Shiboken::AutoDecRef homonymousMethod(getDescriptor(signalData->homonymousMethod, signalData->source, 0));
|
||||||
|
return PyCFunction_Call(homonymousMethod, args, kw);
|
||||||
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
namespace PySide
|
namespace PySide
|
||||||
|
|
@ -503,6 +543,11 @@ void signalInstanceInitialize(PyObject* instance, PyObject* name, SignalData* da
|
||||||
|
|
||||||
self->source = source;
|
self->source = source;
|
||||||
self->signature = signalBuildSignature(self->signalName, data->signatures[index]);
|
self->signature = signalBuildSignature(self->signalName, data->signatures[index]);
|
||||||
|
self->homonymousMethod = 0;
|
||||||
|
if (data->homonymousMethod) {
|
||||||
|
self->homonymousMethod = data->homonymousMethod;
|
||||||
|
Py_INCREF(self->homonymousMethod);
|
||||||
|
}
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (index < data->signaturesSize) {
|
if (index < data->signaturesSize) {
|
||||||
|
|
@ -531,6 +576,7 @@ PyObject* signalNew(const char* name, ...)
|
||||||
self->signaturesSize = 0;
|
self->signaturesSize = 0;
|
||||||
self->signatures = 0;
|
self->signatures = 0;
|
||||||
self->initialized = 0;
|
self->initialized = 0;
|
||||||
|
self->homonymousMethod = 0;
|
||||||
|
|
||||||
va_start(listSignatures, name);
|
va_start(listSignatures, name);
|
||||||
sig = va_arg(listSignatures, char*);
|
sig = va_arg(listSignatures, char*);
|
||||||
|
|
@ -556,5 +602,15 @@ PyObject* signalBuildQtCompatible(const char* signature)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addSignalToWrapper(Shiboken::SbkBaseWrapperType* wrapperType, const char* signalName, PyObject* signal)
|
||||||
|
{
|
||||||
|
PyObject* typeDict = wrapperType->super.ht_type.tp_dict;
|
||||||
|
PyObject* homonymousMethod;
|
||||||
|
if ((homonymousMethod = PyDict_GetItemString(typeDict, signalName))) {
|
||||||
|
Py_INCREF(homonymousMethod);
|
||||||
|
reinterpret_cast<SignalData*>(signal)->homonymousMethod = homonymousMethod;
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(typeDict, signalName, signal);
|
||||||
|
}
|
||||||
|
|
||||||
} //namespace PySide
|
} //namespace PySide
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,11 @@
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Shiboken
|
||||||
|
{
|
||||||
|
struct SbkBaseWrapperType;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
extern PYSIDE_API PyTypeObject PySideSignalInstanceType;
|
extern PYSIDE_API PyTypeObject PySideSignalInstanceType;
|
||||||
|
|
@ -37,6 +42,7 @@ extern "C"
|
||||||
char* signalName;
|
char* signalName;
|
||||||
char* signature;
|
char* signature;
|
||||||
PyObject* source;
|
PyObject* source;
|
||||||
|
PyObject* homonymousMethod;
|
||||||
PyObject* next;
|
PyObject* next;
|
||||||
};
|
};
|
||||||
}; //extern "C"
|
}; //extern "C"
|
||||||
|
|
@ -46,6 +52,7 @@ namespace PySide
|
||||||
|
|
||||||
PYSIDE_API PyObject* signalNew(const char* name, ...);
|
PYSIDE_API PyObject* signalNew(const char* name, ...);
|
||||||
PYSIDE_API void signalUpdateSource(PyObject* source);
|
PYSIDE_API void signalUpdateSource(PyObject* source);
|
||||||
|
PYSIDE_API void addSignalToWrapper(Shiboken::SbkBaseWrapperType* wrapperType, const char* signalName, PyObject* signal);
|
||||||
|
|
||||||
} //namespace PySide
|
} //namespace PySide
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,5 +67,5 @@ target_link_libraries(testbinding
|
||||||
add_dependencies(testbinding pyside QtCore libpyside pysidetest)
|
add_dependencies(testbinding pyside QtCore libpyside pysidetest)
|
||||||
|
|
||||||
|
|
||||||
PYSIDE_TEST(homonimoussignalandmethod_test.py)
|
PYSIDE_TEST(homonymoussignalandmethod_test.py)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
import unittest
|
import unittest
|
||||||
from testbinding import TestObject
|
from testbinding import TestObject
|
||||||
|
|
||||||
'''Tests the behaviour of homonimous signals and slots.'''
|
'''Tests the behaviour of homonymous signals and slots.'''
|
||||||
|
|
||||||
class HomonimousSignalAndMethodTest(unittest.TestCase):
|
class HomonymousSignalAndMethodTest(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.value = 123
|
self.value = 123
|
||||||
|
|
@ -39,13 +39,13 @@ class HomonimousSignalAndMethodTest(unittest.TestCase):
|
||||||
def testCallingInstanceMethodWithoutArguments(self):
|
def testCallingInstanceMethodWithoutArguments(self):
|
||||||
self.assertRaises(TypeError, TestObject.idValue)
|
self.assertRaises(TypeError, TestObject.idValue)
|
||||||
|
|
||||||
def testHomonimousSignalAndMethod(self):
|
def testHomonymousSignalAndMethod(self):
|
||||||
self.assertEqual(self.obj.idValue(), self.value)
|
self.assertEqual(self.obj.idValue(), self.value)
|
||||||
|
|
||||||
def testHomonimousSignalAndStaticMethod(self):
|
def testHomonymousSignalAndStaticMethod(self):
|
||||||
self.assertEqual(TestObject.staticMethodDouble(3), 6)
|
self.assertEqual(TestObject.staticMethodDouble(3), 6)
|
||||||
|
|
||||||
def testHomonimousSignalAndStaticMethodFromInstance(self):
|
def testHomonymousSignalAndStaticMethodFromInstance(self):
|
||||||
self.assertEqual(self.obj.staticMethodDouble(4), 8)
|
self.assertEqual(self.obj.staticMethodDouble(4), 8)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
Loading…
Add table
Add a link
Reference in a new issue