diff options
author | Renato Filho <renato.filho@openbossa.org> | 2011-08-26 15:38:23 -0300 |
---|---|---|
committer | Renato Filho <renato.filho@openbossa.org> | 2011-08-26 17:17:27 -0300 |
commit | 94636bf3be50d5f46dc5928b3e5a920c1cf52888 (patch) | |
tree | 392e9886a315071e477aaf7d602f393240b6e37f /libpyside | |
parent | a8f22c170af12f87eac70e52aedd87558418e929 (diff) | |
download | pyside-94636bf3be50d5f46dc5928b3e5a920c1cf52888.tar.gz pyside-94636bf3be50d5f46dc5928b3e5a920c1cf52888.tar.xz pyside-94636bf3be50d5f46dc5928b3e5a920c1cf52888.zip |
Created utility function to call a python method usign args received in
qt_metacall.
Reviewed by: Hugo Parente <hugo.lima@openbossa.org>
Luciano Wolf <luciano.wolf@openbossa.org>
Diffstat (limited to 'libpyside')
-rw-r--r-- | libpyside/globalreceiverv2.cpp | 36 | ||||
-rw-r--r-- | libpyside/signalmanager.cpp | 224 | ||||
-rw-r--r-- | libpyside/signalmanager.h | 2 |
3 files changed, 136 insertions, 126 deletions
diff --git a/libpyside/globalreceiverv2.cpp b/libpyside/globalreceiverv2.cpp index c31a9d2..748332f 100644 --- a/libpyside/globalreceiverv2.cpp +++ b/libpyside/globalreceiverv2.cpp @@ -52,7 +52,7 @@ class DynamicSlotDataV2 int addSlot(const char* signature); int id(const char* signature) const; - PyObject* call(PyObject* args); + PyObject* callback(); QByteArray hash() const; void notify(); @@ -115,20 +115,17 @@ QByteArray DynamicSlotDataV2::hash(PyObject* callback) return QByteArray::number((qlonglong)PyObject_Hash(callback)); } -PyObject* DynamicSlotDataV2::call(PyObject* args) +PyObject* DynamicSlotDataV2::callback() { PyObject* callback = m_callback; //create a callback based on method data if (m_isMethod) callback = PyMethod_New(m_callback, m_pythonSelf, m_pyClass); + else + Py_INCREF(callback); - PyObject* result = PyObject_CallObject(callback, args); - - if (m_isMethod) - Py_DECREF(callback); - - return result; + return callback; } int DynamicSlotDataV2::id(const char* signature) const @@ -282,26 +279,9 @@ int GlobalReceiverV2::qt_metacall(QMetaObject::Call call, int id, void** args) m_refs.removeAll(obj); // remove all refs to this object decRef(); //remove the safe ref } else { - Shiboken::GilState gil; - PyObject* retval = 0; - - bool isShortCurt = (strstr(slot.signature(), "(") == 0); - if (isShortCurt) { - retval = m_data->call(reinterpret_cast<PyObject*>(args[1])); - } else { - QList<QByteArray> paramTypes = slot.parameterTypes(); - Shiboken::AutoDecRef preparedArgs(PyTuple_New(paramTypes.count())); - for (int i = 0, max = paramTypes.count(); i < max; ++i) { - PyObject* arg = Shiboken::TypeResolver::get(paramTypes[i].constData())->toPython(args[i+1]); // Do not increment the reference - PyTuple_SET_ITEM(preparedArgs.object(), i, arg); - } - retval = m_data->call(preparedArgs); - } - - if (!retval) - PyErr_Print(); - else - Py_DECREF(retval); + bool isShortCuit = (strstr(slot.signature(), "(") == 0); + Shiboken::AutoDecRef callback(m_data->callback()); + SignalManager::callPythonMetaMethod(slot, args, callback, isShortCuit); } return -1; diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp index c0dffd4..bd455c9 100644 --- a/libpyside/signalmanager.cpp +++ b/libpyside/signalmanager.cpp @@ -50,6 +50,12 @@ namespace { static PyObject *metaObjectAttr = 0; + + 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); + static void destroyMetaObject(void* obj) { delete reinterpret_cast<PySide::DynamicQMetaObject*>(obj); @@ -58,7 +64,6 @@ namespace { namespace PySide { -static int callMethod(QObject* object, int id, void** args); PyObjectWrapper::PyObjectWrapper() :m_me(Py_None) @@ -309,58 +314,6 @@ int SignalManager::globalReceiverSlotIndex(QObject* receiver, const char* signat return reinterpret_cast<GlobalReceiverV2*>(receiver)->addSlot(signature); } -static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* args) -{ - void* signalArgs[2] = {0, args}; - source->qt_metacall(QMetaObject::InvokeMetaMethod, signalIndex, signalArgs); - 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; -} - bool SignalManager::emitSignal(QObject* source, const char* signal, PyObject* args) { if (!Signal::checkQtSignal(signal)) @@ -444,60 +397,36 @@ int SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, int id, return id; } -static int PySide::callMethod(QObject* object, int id, void** args) +int SignalManager::callPythonMetaMethod(const QMetaMethod& method, void** args, PyObject* pyMethod, bool isShortCuit) { - const QMetaObject* metaObject = object->metaObject(); - QMetaMethod method = metaObject->method(id); + Q_ASSERT(pyMethod); - if (method.methodType() == QMetaMethod::Signal) { - // emit python signal - QMetaObject::activate(object, id, args); - } else { - // call python slot - Shiboken::GilState gil; - QList<QByteArray> paramTypes = method.parameterTypes(); - PyObject* self = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(object); - PyObject* preparedArgs = NULL; - Py_ssize_t argsSize = paramTypes.count(); + Shiboken::GilState gil; + PyObject* pyArguments = NULL; - if (argsSize) - preparedArgs = PyTuple_New(argsSize); + if (isShortCuit) + pyArguments = reinterpret_cast<PyObject*>(args[1]); + else + pyArguments = parseArguments(method.parameterTypes(), args); - for (int i = 0, max = paramTypes.count(); i < max; ++i) { - void* data = args[i+1]; - const char* dataType = paramTypes[i].constData(); + //keep the returnType this call be destroyed after method call + QByteArray returnType = method.typeName(); - Shiboken::TypeResolver* tr = Shiboken::TypeResolver::get(dataType); - if (tr) { - PyObject* arg = tr->toPython(data); - PyTuple_SET_ITEM(preparedArgs, i, arg); - } else { - PyErr_Format(PyExc_TypeError, "Can't call meta function because I have no idea how to handle %s", dataType); - return -1; - } - } + Shiboken::AutoDecRef retval(PyObject_CallObject(pyMethod, pyArguments)); - QString methodName = method.signature(); - methodName = methodName.left(methodName.indexOf('(')); + if (!isShortCuit) + Py_XDECREF(pyArguments); - Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(self, qPrintable(methodName))); - if (!pyMethod.isNull()) { - Shiboken::AutoDecRef retval(PyObject_CallObject(pyMethod, preparedArgs)); - if (retval.isNull()) { - qWarning() << "Error calling slot" << methodName; - PyErr_Print(); - } else { - const char* returnType = method.typeName(); - if (returnType && (strlen(returnType) > 0)) - Shiboken::TypeResolver::get(returnType)->toCpp(retval, &args[0]); - } - } else { - qWarning() << "Dynamic slot" << methodName << "not found!"; - } - Py_XDECREF(preparedArgs); + if (retval.isNull()) { + PyErr_Print(); + } else { + if (returnType.size() > 0) + Shiboken::TypeResolver::get(returnType)->toCpp(retval, &args[0]); } + return -1; } + bool SignalManager::registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type) { int ret = registerMetaMethodGetIndex(source, signature, type); @@ -544,7 +473,6 @@ bool SignalManager::hasConnectionWith(const QObject *object) return m_d->m_globalReceiver.hasConnectionWith(object); } - const QMetaObject* SignalManager::retriveMetaObject(PyObject *self) { Shiboken::GilState gil; @@ -563,4 +491,104 @@ const QMetaObject* SignalManager::retriveMetaObject(PyObject *self) return mo; } +namespace { + +static int callMethod(QObject* object, int id, void** args) +{ + const QMetaObject* metaObject = object->metaObject(); + QMetaMethod method = metaObject->method(id); + + if (method.methodType() == QMetaMethod::Signal) { + // emit python signal + QMetaObject::activate(object, id, args); + } else { + Shiboken::GilState gil; + PyObject* self = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(object); + QByteArray methodName = method.signature(); + methodName = methodName.left(methodName.indexOf('(')); + Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(self, methodName)); + SignalManager::callPythonMetaMethod(method, args, pyMethod, false); + } + return -1; +} + + +static PyObject* parseArguments(QList<QByteArray> paramTypes, void** args) +{ + PyObject* preparedArgs = NULL; + Py_ssize_t argsSize = paramTypes.count(); + + if (argsSize) + preparedArgs = PyTuple_New(argsSize); + + for (int i = 0, max = paramTypes.count(); i < max; ++i) { + void* data = args[i+1]; + const char* dataType = paramTypes[i].constData(); + + Shiboken::TypeResolver* tr = Shiboken::TypeResolver::get(dataType); + if (tr) { + PyObject* arg = tr->toPython(data); + PyTuple_SET_ITEM(preparedArgs, i, arg); + } else { + PyErr_Format(PyExc_TypeError, "Can't call meta function because I have no idea how to handle %s", dataType); + Py_DECREF(preparedArgs); + return NULL; + } + } + + return preparedArgs; +} + +static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* args) +{ + void* signalArgs[2] = {0, args}; + source->qt_metacall(QMetaObject::InvokeMetaMethod, signalIndex, signalArgs); + 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 diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h index 1c8ecfc..744cf9e 100644 --- a/libpyside/signalmanager.h +++ b/libpyside/signalmanager.h @@ -79,6 +79,8 @@ public: // Disconnect all signals managed by Globalreceiver void clear(); + // Utility function to call a python method usign args received in qt_metacall + static int callPythonMetaMethod(const QMetaMethod& method, void** args, PyObject* obj, bool isShortCuit); PYSIDE_DEPRECATED(QObject* globalReceiver()); PYSIDE_DEPRECATED(void addGlobalSlot(const char* slot, PyObject* callback)); |