Implemente sequence operator on signal class.
Reviewer: Hugo Parente Lima <hugo.lima@openbossa.org>,
Luciano Wolf <luciano.wolf@openbossa.org>
This commit is contained in:
parent
d8593de73a
commit
5eabe6943f
3 changed files with 118 additions and 64 deletions
|
|
@ -23,12 +23,14 @@ static void qsignal_instance_free(void*);
|
||||||
static PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kw);
|
static PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kw);
|
||||||
static PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args);
|
static PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args);
|
||||||
static PyObject* qsignal_instance_emit(PyObject *self, PyObject *args);
|
static PyObject* qsignal_instance_emit(PyObject *self, PyObject *args);
|
||||||
|
static PyObject* qsignal_instance_get_item(PyObject *self, PyObject *key);
|
||||||
|
|
||||||
//aux
|
//aux
|
||||||
static char* qsignal_build_signature(const char *name, const char *signature);
|
static char* qsignal_build_signature(const char *name, const char *signature);
|
||||||
static const char* qsignal_get_type_name(PyObject *type);
|
static const char* qsignal_get_type_name(PyObject *type);
|
||||||
static void qsignal_append_signature(SignalData *self, PyObject *args);
|
static void qsignal_append_signature(SignalData *self, PyObject *args);
|
||||||
static void qsignal_instance_initialize(PyObject *instance, PyObject *name, SignalData *data, PyObject *source);
|
static void qsignal_instance_initialize(PyObject *instance, PyObject *name, SignalData *data, PyObject *source, int index);
|
||||||
|
static char* qsignal_parse_signature(PyObject *args);
|
||||||
|
|
||||||
PyTypeObject PySideSignal_Type = {
|
PyTypeObject PySideSignal_Type = {
|
||||||
PyObject_HEAD_INIT(0)
|
PyObject_HEAD_INIT(0)
|
||||||
|
|
@ -87,11 +89,17 @@ static PyMethodDef PySideQtSignalInstance_methods[] = {
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyMappingMethods PySideQSignalInstance_as_mapping = {
|
||||||
|
0,
|
||||||
|
qsignal_instance_get_item,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
PyTypeObject PySideSignalInstance_Type = {
|
PyTypeObject PySideSignalInstance_Type = {
|
||||||
PyObject_HEAD_INIT(0)
|
PyObject_HEAD_INIT(0)
|
||||||
0, /*ob_size*/
|
0, /*ob_size*/
|
||||||
SIGNAL_CLASS_NAME, /*tp_name*/
|
SIGNAL_CLASS_NAME, /*tp_name*/
|
||||||
sizeof(SignalData), /*tp_basicsize*/
|
sizeof(SignalInstanceData),/*tp_basicsize*/
|
||||||
0, /*tp_itemsize*/
|
0, /*tp_itemsize*/
|
||||||
0, /*tp_dealloc*/
|
0, /*tp_dealloc*/
|
||||||
0, /*tp_print*/
|
0, /*tp_print*/
|
||||||
|
|
@ -101,7 +109,7 @@ PyTypeObject PySideSignalInstance_Type = {
|
||||||
0, /*tp_repr*/
|
0, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
&PySideQSignalInstance_as_mapping, /*tp_as_mapping*/
|
||||||
0, /*tp_hash */
|
0, /*tp_hash */
|
||||||
0, /*tp_call*/
|
0, /*tp_call*/
|
||||||
0, /*tp_str*/
|
0, /*tp_str*/
|
||||||
|
|
@ -109,7 +117,7 @@ PyTypeObject PySideSignalInstance_Type = {
|
||||||
0, /*tp_setattro*/
|
0, /*tp_setattro*/
|
||||||
0, /*tp_as_buffer*/
|
0, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||||||
SIGNAL_CLASS_NAME"I", /*tp_doc */
|
SIGNAL_CLASS_NAME, /*tp_doc */
|
||||||
0, /*tp_traverse */
|
0, /*tp_traverse */
|
||||||
0, /*tp_clear */
|
0, /*tp_clear */
|
||||||
0, /*tp_richcompare */
|
0, /*tp_richcompare */
|
||||||
|
|
@ -119,7 +127,7 @@ PyTypeObject PySideSignalInstance_Type = {
|
||||||
PySideQtSignalInstance_methods, /*tp_methods */
|
PySideQtSignalInstance_methods, /*tp_methods */
|
||||||
0, /*tp_members */
|
0, /*tp_members */
|
||||||
0, /*tp_getset */
|
0, /*tp_getset */
|
||||||
&PySideSignal_Type, /*tp_base */
|
0, /*tp_base */
|
||||||
0, /*tp_dict */
|
0, /*tp_dict */
|
||||||
0, /*tp_descr_get */
|
0, /*tp_descr_get */
|
||||||
0, /*tp_descr_set */
|
0, /*tp_descr_set */
|
||||||
|
|
@ -155,6 +163,27 @@ PyAPI_FUNC(void) init_signal(PyObject* module)
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* qsignal_instance_get_item(PyObject *self, PyObject *key)
|
||||||
|
{
|
||||||
|
SignalInstanceData *data = reinterpret_cast<SignalInstanceData*>(self);
|
||||||
|
char *sig_key = qsignal_parse_signature(key);
|
||||||
|
char *sig = qsignal_build_signature(data->signal_name, sig_key);
|
||||||
|
free(sig_key);
|
||||||
|
|
||||||
|
while(data) {
|
||||||
|
if (strcmp(data->signature, sig) == 0) {
|
||||||
|
free(sig);
|
||||||
|
PyObject *result = reinterpret_cast<PyObject*>(data);
|
||||||
|
Py_INCREF(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
data = reinterpret_cast<SignalInstanceData*>(data->next);
|
||||||
|
}
|
||||||
|
free(sig);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void signal_update_source(PyObject *source)
|
void signal_update_source(PyObject *source)
|
||||||
{
|
{
|
||||||
PyObject *key, *value;
|
PyObject *key, *value;
|
||||||
|
|
@ -162,17 +191,12 @@ void signal_update_source(PyObject *source)
|
||||||
PyTypeObject *obType = source->ob_type;
|
PyTypeObject *obType = source->ob_type;
|
||||||
|
|
||||||
while (PyDict_Next(obType->tp_dict, &pos, &key, &value)) {
|
while (PyDict_Next(obType->tp_dict, &pos, &key, &value)) {
|
||||||
|
|
||||||
if (value->ob_type == &PySideSignal_Type) {
|
if (value->ob_type == &PySideSignal_Type) {
|
||||||
PyObject *signal_instance = (PyObject*)PyObject_New(SignalData, &PySideSignalInstance_Type);
|
PyObject *signal_instance = (PyObject*)PyObject_New(SignalData, &PySideSignalInstance_Type);
|
||||||
|
qsignal_instance_initialize(signal_instance, key, reinterpret_cast<SignalData*>(value), source, 0);
|
||||||
qsignal_instance_initialize(signal_instance, key, reinterpret_cast<SignalData*>(value), source);
|
|
||||||
|
|
||||||
PyObject_SetAttr(source, key, signal_instance);
|
PyObject_SetAttr(source, key, signal_instance);
|
||||||
Py_DECREF(signal_instance);
|
Py_DECREF(signal_instance);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,14 +215,16 @@ const char* qsignal_get_type_name(PyObject *type)
|
||||||
char* qsignal_build_signature(const char *name, const char *signature)
|
char* qsignal_build_signature(const char *name, const char *signature)
|
||||||
{
|
{
|
||||||
QString signal;
|
QString signal;
|
||||||
signal.sprintf("2%s(%s)", name, (signature ? signature : "()"));
|
|
||||||
return strdup(QMetaObject::normalizedSignature(signal.toAscii()));
|
return strdup(QMetaObject::normalizedSignature(signal.toAscii()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void qsignal_append_signature(SignalData *self, PyObject *args)
|
char* qsignal_parse_signature(PyObject *args)
|
||||||
{
|
{
|
||||||
char *signature = 0;
|
char *signature = 0;
|
||||||
|
|
||||||
|
if (args && !PySequence_Check(args) && (args != Py_None && args))
|
||||||
|
return strdup(qsignal_get_type_name(args));
|
||||||
|
|
||||||
for(Py_ssize_t i=0, i_max=PySequence_Size(args); i < i_max; i++) {
|
for(Py_ssize_t i=0, i_max=PySequence_Size(args); i < i_max; i++) {
|
||||||
Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
|
Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
|
||||||
const char *type_name = qsignal_get_type_name(arg);
|
const char *type_name = qsignal_get_type_name(arg);
|
||||||
|
|
@ -212,6 +238,13 @@ void qsignal_append_signature(SignalData *self, PyObject *args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qsignal_append_signature(SignalData *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char *signature = qsignal_parse_signature(args);
|
||||||
|
|
||||||
self->signatures_size++;
|
self->signatures_size++;
|
||||||
|
|
||||||
if (self->signatures_size > 1) {
|
if (self->signatures_size > 1) {
|
||||||
|
|
@ -271,33 +304,46 @@ void qsignal_free(void *self)
|
||||||
data->initialized = false;
|
data->initialized = false;
|
||||||
data->signatures_size = 0;
|
data->signatures_size = 0;
|
||||||
|
|
||||||
pySelf->ob_type->tp_free (self);
|
pySelf->ob_type->tp_base->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qsignal_instance_free(void *self)
|
void qsignal_instance_free(void *self)
|
||||||
{
|
{
|
||||||
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
|
PyObject *pySelf = reinterpret_cast<PyObject*>(self);
|
||||||
qsignal_free(self);
|
SignalInstanceData *data = reinterpret_cast<SignalInstanceData*>(self);
|
||||||
pySelf->ob_type->tp_free(self);
|
|
||||||
|
free(data->signal_name);
|
||||||
|
free(data->signature);
|
||||||
|
|
||||||
|
while(data) {
|
||||||
|
Py_XDECREF(data->next);
|
||||||
|
data = reinterpret_cast<SignalInstanceData*>(data->next);
|
||||||
|
}
|
||||||
|
pySelf->ob_type->tp_base->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qsignal_instance_initialize(PyObject *instance, PyObject *name, SignalData *data, PyObject *source)
|
void qsignal_instance_initialize(PyObject *instance, PyObject *name, SignalData *data, PyObject *source, int index)
|
||||||
{
|
{
|
||||||
SignalData *self = reinterpret_cast<SignalData*>(instance);
|
if (data->initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SignalInstanceData *self = reinterpret_cast<SignalInstanceData*>(instance);
|
||||||
if (data->signal_name)
|
if (data->signal_name)
|
||||||
self->signal_name = strdup(data->signal_name);
|
self->signal_name = strdup(data->signal_name);
|
||||||
else
|
else
|
||||||
self->signal_name = strdup(PyString_AsString(name));
|
self->signal_name = strdup(PyString_AsString(name));
|
||||||
|
|
||||||
self->signatures_size = data->signatures_size;
|
|
||||||
self->initialized = true;
|
|
||||||
self->source = source;
|
self->source = source;
|
||||||
data->initialized = true;
|
self->signature = qsignal_build_signature(self->signal_name, data->signatures[index]);
|
||||||
|
index++;
|
||||||
|
|
||||||
self->signatures = (char**) malloc(sizeof(char**) * self->signatures_size);
|
if (index < data->signatures_size) {
|
||||||
///build signature
|
self->next = (PyObject*)PyObject_New(SignalData, &PySideSignalInstance_Type);
|
||||||
for(int i=0, i_max=self->signatures_size; i < i_max; i++)
|
qsignal_instance_initialize(self->next, name, data, source, index);
|
||||||
self->signatures[i] = qsignal_build_signature(self->signal_name, data->signatures[i]);
|
}
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
data->initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kwds)
|
PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
|
@ -310,32 +356,28 @@ PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kwd
|
||||||
"O|O:"SIGNAL_CLASS_NAME, (char**) kwlist, &slot, &type))
|
"O|O:"SIGNAL_CLASS_NAME, (char**) kwlist, &slot, &type))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
SignalData *source = reinterpret_cast<SignalData*>(self);
|
SignalInstanceData *source = reinterpret_cast<SignalInstanceData*>(self);
|
||||||
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
if (slot->ob_type == &PySideSignal_Type) {
|
if (slot->ob_type == &PySideSignalInstance_Type) {
|
||||||
SignalData *target = reinterpret_cast<SignalData*>(slot);
|
//TODO: find best match
|
||||||
for(int s, s_max=source->signatures_size; s < s_max; s++) {
|
SignalInstanceData *target = reinterpret_cast<SignalInstanceData*>(slot);
|
||||||
for(int t, t_max=target->signatures_size; t < t_max; t++) {
|
|
||||||
if (QMetaObject::checkConnectArgs(source->signatures[s], target->signatures[t])) {
|
if (QMetaObject::checkConnectArgs(source->signature, target->signature)) {
|
||||||
PyList_Append(pyArgs, source->source);
|
PyList_Append(pyArgs, source->source);
|
||||||
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[s]));
|
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signature));
|
||||||
PyList_Append(pyArgs, source_signature);
|
PyList_Append(pyArgs, source_signature);
|
||||||
|
|
||||||
PyList_Append(pyArgs, target->source);
|
PyList_Append(pyArgs, target->source);
|
||||||
Shiboken::AutoDecRef target_signature(PyString_FromString(source->signatures[s]));
|
Shiboken::AutoDecRef target_signature(PyString_FromString(target->signature));
|
||||||
PyList_Append(pyArgs, target_signature);
|
PyList_Append(pyArgs, target_signature);
|
||||||
match = true;
|
match = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match) break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//try the first signature
|
//try the first signature
|
||||||
PyList_Append(pyArgs, source->source);
|
PyList_Append(pyArgs, source->source);
|
||||||
Shiboken::AutoDecRef signature(PyString_FromString(source->signatures[0]));
|
Shiboken::AutoDecRef signature(PyString_FromString(source->signature));
|
||||||
PyList_Append(pyArgs, signature);
|
PyList_Append(pyArgs, signature);
|
||||||
|
|
||||||
PyList_Append(pyArgs, slot);
|
PyList_Append(pyArgs, slot);
|
||||||
|
|
@ -353,7 +395,7 @@ PyObject* qsignal_instance_connect(PyObject *self, PyObject *args, PyObject *kwd
|
||||||
|
|
||||||
PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args)
|
PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
SignalData *source = reinterpret_cast<SignalData*>(self);
|
SignalInstanceData *source = reinterpret_cast<SignalInstanceData*>(self);
|
||||||
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
||||||
|
|
||||||
PyObject *slot;
|
PyObject *slot;
|
||||||
|
|
@ -363,28 +405,22 @@ PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args)
|
||||||
slot = args;
|
slot = args;
|
||||||
|
|
||||||
bool match = false;
|
bool match = false;
|
||||||
if (slot->ob_type == &PySideSignal_Type) {
|
if (slot->ob_type == &PySideSignalInstance_Type) {
|
||||||
SignalData *target = reinterpret_cast<SignalData*>(slot);
|
SignalInstanceData *target = reinterpret_cast<SignalInstanceData*>(slot);
|
||||||
for(int s, s_max=source->signatures_size; s < s_max; s++) {
|
if (QMetaObject::checkConnectArgs(source->signature, target->signature)) {
|
||||||
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);
|
PyList_Append(pyArgs, source->source);
|
||||||
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[s]));
|
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signature));
|
||||||
PyList_Append(pyArgs, source_signature);
|
PyList_Append(pyArgs, source_signature);
|
||||||
|
|
||||||
PyList_Append(pyArgs, target->source);
|
PyList_Append(pyArgs, target->source);
|
||||||
Shiboken::AutoDecRef target_signature(PyString_FromString(source->signatures[s]));
|
Shiboken::AutoDecRef target_signature(PyString_FromString(target->signature));
|
||||||
PyList_Append(pyArgs, target_signature);
|
PyList_Append(pyArgs, target_signature);
|
||||||
match = true;
|
match = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (match) break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//try the first signature
|
//try the first signature
|
||||||
PyList_Append(pyArgs, source->source);
|
PyList_Append(pyArgs, source->source);
|
||||||
Shiboken::AutoDecRef signature(PyString_FromString(source->signatures[0]));
|
Shiboken::AutoDecRef signature(PyString_FromString(source->signature));
|
||||||
PyList_Append(pyArgs, signature);
|
PyList_Append(pyArgs, signature);
|
||||||
|
|
||||||
PyList_Append(pyArgs, slot);
|
PyList_Append(pyArgs, slot);
|
||||||
|
|
@ -402,10 +438,10 @@ PyObject* qsignal_instance_disconnect(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
PyObject* qsignal_instance_emit(PyObject *self, PyObject *args)
|
PyObject* qsignal_instance_emit(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
SignalData *source = reinterpret_cast<SignalData*>(self);
|
SignalInstanceData *source = reinterpret_cast<SignalInstanceData*>(self);
|
||||||
|
|
||||||
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
Shiboken::AutoDecRef pyArgs(PyList_New(0));
|
||||||
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signatures[0]));
|
Shiboken::AutoDecRef source_signature(PyString_FromString(source->signature));
|
||||||
|
|
||||||
PyList_Append(pyArgs, source_signature);
|
PyList_Append(pyArgs, source_signature);
|
||||||
for(Py_ssize_t i=0, i_max=PyTuple_Size(args); i < i_max; i++)
|
for(Py_ssize_t i=0, i_max=PyTuple_Size(args); i < i_max; i++)
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,17 @@ typedef struct {
|
||||||
char *signal_name;
|
char *signal_name;
|
||||||
char **signatures;
|
char **signatures;
|
||||||
int signatures_size;
|
int signatures_size;
|
||||||
PyObject *source;
|
|
||||||
} SignalData;
|
} SignalData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
char *signal_name;
|
||||||
|
char *signature;
|
||||||
|
PyObject *source;
|
||||||
|
PyObject *next;
|
||||||
|
} SignalInstanceData;
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
PyAPI_DATA(PyTypeObject) PySideSignal_Type;
|
PyAPI_DATA(PyTypeObject) PySideSignal_Type;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class MyObject(QObject):
|
||||||
sig1 = Signal()
|
sig1 = Signal()
|
||||||
sig2 = Signal(int, name='rangeChanged')
|
sig2 = Signal(int, name='rangeChanged')
|
||||||
sig3 = Signal(int)
|
sig3 = Signal(int)
|
||||||
|
sig4 = Signal((int,), (QString,))
|
||||||
|
|
||||||
|
|
||||||
@Slot(int)
|
@Slot(int)
|
||||||
|
|
@ -21,6 +22,9 @@ class MyObject(QObject):
|
||||||
def slot1(self):
|
def slot1(self):
|
||||||
self._called = True
|
self._called = True
|
||||||
|
|
||||||
|
def slotString(self, s):
|
||||||
|
self._s = s
|
||||||
|
|
||||||
|
|
||||||
class SignalObjectTest(unittest.TestCase):
|
class SignalObjectTest(unittest.TestCase):
|
||||||
def testsingleConnect(self):
|
def testsingleConnect(self):
|
||||||
|
|
@ -40,5 +44,11 @@ class SignalObjectTest(unittest.TestCase):
|
||||||
o.sig2.connect(o.myRange)
|
o.sig2.connect(o.myRange)
|
||||||
o.sig2.emit(10)
|
o.sig2.emit(10)
|
||||||
|
|
||||||
|
def testDictOperator(self):
|
||||||
|
o = MyObject()
|
||||||
|
o.sig4[QString].connect(o.slotString)
|
||||||
|
o.sig4[QString].emit("PySide")
|
||||||
|
self.assertEqual(o._s, "PySide")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue