aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2011-08-26 15:38:23 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:54:47 -0300
commitd5b645d3ab8faa5aa5887e7fecf370f7ef322bba (patch)
treedd0f50bf04f0dc9345da32a75b97a2f5dc1ecb66 /libpyside
parent65d4cf2be4bf6071b03c9ae34368d9cffda597e5 (diff)
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.cpp36
-rw-r--r--libpyside/signalmanager.cpp224
-rw-r--r--libpyside/signalmanager.h2
3 files changed, 136 insertions, 126 deletions
diff --git a/libpyside/globalreceiverv2.cpp b/libpyside/globalreceiverv2.cpp
index c31a9d2f6..748332f96 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 c0dffd431..bd455c9c3 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 1c8ecfc2e..744cf9e5f 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));