diff options
author | Hugo Parente Lima <hugo.pl@gmail.com> | 2011-10-26 20:17:56 -0200 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:56:15 -0300 |
commit | 67d6455fa52921d631001e7938aa7b9fa40b45aa (patch) | |
tree | 11e72784d6dea502c8df4089f20bceea666c3ff4 /libpyside | |
parent | 15ceed791f8dda4aa1256e67c11f8a748ce4b7b0 (diff) |
Unify the code used to do QObject meta calls.
Diffstat (limited to 'libpyside')
-rw-r--r-- | libpyside/pysidemetafunction.cpp | 106 | ||||
-rw-r--r-- | libpyside/pysidemetafunction_p.h | 10 | ||||
-rw-r--r-- | libpyside/signalmanager.cpp | 57 |
3 files changed, 80 insertions, 93 deletions
diff --git a/libpyside/pysidemetafunction.cpp b/libpyside/pysidemetafunction.cpp index de4d3244a..cb6b8612e 100644 --- a/libpyside/pysidemetafunction.cpp +++ b/libpyside/pysidemetafunction.cpp @@ -21,6 +21,7 @@ */ #include <sbkpython.h> #include "pysidemetafunction.h" +#include "pysidemetafunction_p.h" #include <shiboken.h> #include <QObject> @@ -98,15 +99,55 @@ void functionFree(void *self) PyObject* functionCall(PyObject* self, PyObject* args, PyObject* kw) { PySideMetaFunction* function = reinterpret_cast<PySideMetaFunction*>(self); - QMetaMethod method = function->d->method; + + PyObject* retVal; + if (!PySide::MetaFunction::call(function->d->qobject, function->d->method.methodIndex(), args, &retVal)) + return 0; + return retVal; +} + +} // extern "C" + +namespace PySide { namespace MetaFunction { + +void init(PyObject* module) +{ + if (PyType_Ready(&PySideMetaFunctionType) < 0) + return; + + PyModule_AddObject(module, "MetaFunction", ((PyObject*)&PySideMetaFunctionType)); +} + +PySideMetaFunction* newObject(QObject* source, int methodIndex) +{ + if (methodIndex >= source->metaObject()->methodCount()) + return 0; + + QMetaMethod method = source->metaObject()->method(methodIndex); + if ((method.methodType() == QMetaMethod::Slot) || + (method.methodType() == QMetaMethod::Method)) { + PySideMetaFunction* function = PyObject_New(PySideMetaFunction, &PySideMetaFunctionType); + function->d = new PySideMetaFunctionPrivate(); + function->d->qobject = source; + function->d->method = method; + return function; + } + return 0; +} + +bool call(QObject* self, int methodIndex, PyObject* args, PyObject** retVal) +{ + + QMetaMethod method = self->metaObject()->method(methodIndex); QList<QByteArray> argTypes = method.parameterTypes(); // args given plus return type - int numArgs = PyTuple_GET_SIZE(args) + 1; + Shiboken::AutoDecRef sequence(PySequence_Fast(args, 0)); + int numArgs = PySequence_Fast_GET_SIZE(sequence.object()) + 1; if (numArgs - 1 != argTypes.count()) { PyErr_Format(PyExc_TypeError, "%s only accepts %d arguments, %d given!", method.signature(), argTypes.count(), numArgs); - return 0; + return false; } QVariant* methValues = new QVariant[numArgs]; @@ -133,63 +174,44 @@ PyObject* functionCall(PyObject* self, PyObject* args, PyObject* kw) if (Shiboken::TypeResolver::getType(typeName) == Shiboken::TypeResolver::ValueType) { int typeId = QMetaType::type(typeName); if (!typeId) { - PyErr_Format(PyExc_TypeError, "Value type used on signal needs to be registered on meta type: %s", typeName.data()); + PyErr_Format(PyExc_TypeError, "Value types used on meta functions (including signals) need to be " + "registered on meta type: %s", typeName.data()); break; } methValues[i] = QVariant(typeId, (void*) 0); } methArgs[i] = methValues[i].data(); if (i != 0) // Don't do this for return type - typeResolver->toCpp(PyTuple_GET_ITEM(args, i - 1), &methArgs[i]); + typeResolver->toCpp(PySequence_Fast_GET_ITEM(sequence.object(), i - 1), &methArgs[i]); } else { - PyErr_Format(PyExc_TypeError, "Unknown type used to emit a signal: %s", argTypes[i].constData()); + PyErr_Format(PyExc_TypeError, "Unknown type used to call meta function (that may be a signal): %s", argTypes[i].constData()); break; } } bool ok = i == numArgs; - if (ok) - QMetaObject::metacall(function->d->qobject, QMetaObject::InvokeMetaMethod, method.methodIndex(), methArgs); - - static Shiboken::TypeResolver* qVariantTypeResolver = Shiboken::TypeResolver::get("QVariant"); - Q_ASSERT(qVariantTypeResolver); - - PyObject* retVal = qVariantTypeResolver->toPython(&methValues[0]); + if (ok) { + QMetaObject::metacall(self, QMetaObject::InvokeMetaMethod, method.methodIndex(), methArgs); + + if (retVal) { + if (methArgs[0]) { + static Shiboken::TypeResolver* qVariantTypeResolver = Shiboken::TypeResolver::get("QVariant"); + Q_ASSERT(qVariantTypeResolver); + + *retVal = qVariantTypeResolver->toPython(&methValues[0]); + } else { + *retVal = Py_None; + Py_INCREF(*retVal); + } + } + } delete[] methArgs; delete[] methValues; - return retVal; + return ok; } -} // extern "C" - -namespace PySide { namespace MetaFunction { - -void init(PyObject* module) -{ - if (PyType_Ready(&PySideMetaFunctionType) < 0) - return; - - PyModule_AddObject(module, "MetaFunction", ((PyObject*)&PySideMetaFunctionType)); -} - -PySideMetaFunction* newObject(QObject* source, int methodIndex) -{ - if (methodIndex >= source->metaObject()->methodCount()) - return 0; - - QMetaMethod method = source->metaObject()->method(methodIndex); - if ((method.methodType() == QMetaMethod::Slot) || - (method.methodType() == QMetaMethod::Method)) { - PySideMetaFunction* function = PyObject_New(PySideMetaFunction, &PySideMetaFunctionType); - function->d = new PySideMetaFunctionPrivate(); - function->d->qobject = source; - function->d->method = method; - return function; - } - return 0; -} } //namespace MetaFunction } //namespace PySide diff --git a/libpyside/pysidemetafunction_p.h b/libpyside/pysidemetafunction_p.h index ebbf42472..7e2af4d21 100644 --- a/libpyside/pysidemetafunction_p.h +++ b/libpyside/pysidemetafunction_p.h @@ -24,10 +24,18 @@ #define PYSIDE_METAFUNCTION_P_H #include <sbkpython.h> +#include <QList> +#include <QByteArray> + +class QObject; namespace PySide { namespace MetaFunction { - void init(PyObject* module); + void init(PyObject* module); + /** + * Does a Qt metacall on a QObject + */ + bool call(QObject* self, int methodIndex, PyObject* args, PyObject** retVal = 0); } //namespace MetaFunction } //namespace PySide diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp index 8e5f2e613..a95f5f130 100644 --- a/libpyside/signalmanager.cpp +++ b/libpyside/signalmanager.cpp @@ -26,6 +26,7 @@ #include "pysideproperty_p.h" #include "pyside.h" #include "dynamicqmetaobject.h" +#include "pysidemetafunction_p.h" #include <QHash> #include <QStringList> @@ -34,6 +35,7 @@ #include <gilstate.h> #include <QDebug> #include <limits> +#include <algorithm> #include <typeresolver.h> #include <basewrapper.h> #include <conversions.h> @@ -54,7 +56,6 @@ namespace { static int callMethod(QObject* object, int id, void** args); static PyObject* parseArguments(QList<QByteArray> paramTypese, void** args); static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* args); - static bool emitNormalSignal(QObject* source, int signalIndex, const char* signal, PyObject* args, const QStringList& argTypes); #ifdef IS_PY3K static void destroyMetaObject(PyObject* obj) @@ -338,13 +339,14 @@ bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* ar int signalIndex = source->metaObject()->indexOfSignal(signal); if (signalIndex != -1) { - bool isShortCircuit; - QStringList argTypes = Signal::getArgsFromSignature(signal, &isShortCircuit); - + // cryptic but works! + // if the signature doesn't have a '(' it's a shor circuited signal, i.e. std::find + // returned the string null terminator. + bool isShortCircuit = !*std::find(signal, signal + std::strlen(signal), '('); if (isShortCircuit) return emitShortCircuitSignal(source, signalIndex, args); else - return emitNormalSignal(source, signalIndex, signal, args, argTypes); + return MetaFunction::call(source, signalIndex, args); } return false; } @@ -572,49 +574,4 @@ static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* a return true; } -static bool emitNormalSignal(QObject* source, int signalIndex, const char* signal, PyObject* args, const QStringList& argTypes) -{ - Shiboken::AutoDecRef sequence(PySequence_Fast(args, 0)); - int argsGiven = PySequence_Fast_GET_SIZE(sequence.object()); - - if (argsGiven != argTypes.count()) { - PyErr_Format(PyExc_TypeError, "%s only accepts %d arguments, %d given!", signal, argTypes.count(), argsGiven); - return false; - } - - QVariant* signalValues = new QVariant[argsGiven]; - void** signalArgs = new void*[argsGiven + 1]; - signalArgs[0] = 0; - - int i; - for (i = 0; i < argsGiven; ++i) { - QByteArray typeName = argTypes[i].toAscii(); - Shiboken::TypeResolver* typeResolver = Shiboken::TypeResolver::get(typeName); - if (typeResolver) { - if (Shiboken::TypeResolver::getType(typeName) == Shiboken::TypeResolver::ValueType) { - int typeId = QMetaType::type(typeName); - if (!typeId) { - PyErr_Format(PyExc_TypeError, "Value type used on signal needs to be registered on meta type: %s", typeName.data()); - break; - } - signalValues[i] = QVariant(typeId, (void*) 0); - } - signalArgs[i+1] = signalValues[i].data(); - typeResolver->toCpp(PySequence_Fast_GET_ITEM(sequence.object(), i), &signalArgs[i+1]); - } else { - PyErr_Format(PyExc_TypeError, "Unknown type used to emit a signal: %s", qPrintable(argTypes[i])); - break; - } - } - - bool ok = i == argsGiven; - if (ok) - source->qt_metacall(QMetaObject::InvokeMetaMethod, signalIndex, signalArgs); - - delete[] signalArgs; - delete[] signalValues; - - return ok; -} - } //namespace |