aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2011-10-26 20:17:56 -0200
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:56:15 -0300
commit67d6455fa52921d631001e7938aa7b9fa40b45aa (patch)
tree11e72784d6dea502c8df4089f20bceea666c3ff4 /libpyside
parent15ceed791f8dda4aa1256e67c11f8a748ce4b7b0 (diff)
Unify the code used to do QObject meta calls.
Diffstat (limited to 'libpyside')
-rw-r--r--libpyside/pysidemetafunction.cpp106
-rw-r--r--libpyside/pysidemetafunction_p.h10
-rw-r--r--libpyside/signalmanager.cpp57
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