aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6')
-rw-r--r--sources/pyside6/libpyside/pysideproperty.cpp3
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp187
2 files changed, 99 insertions, 91 deletions
diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp
index 8053a63ba..d6dda6708 100644
--- a/sources/pyside6/libpyside/pysideproperty.cpp
+++ b/sources/pyside6/libpyside/pysideproperty.cpp
@@ -129,7 +129,6 @@ static void qpropertyMetaCall(PySideProperty *pp, PyObject *self, QMetaObject::C
switch(call) {
case QMetaObject::ReadProperty:
{
- Shiboken::GilState gil;
PyObject *value = PySide::Property::getValue(pp, self);
if (value) {
converter.toCpp(value, args[0]);
@@ -140,7 +139,6 @@ static void qpropertyMetaCall(PySideProperty *pp, PyObject *self, QMetaObject::C
case QMetaObject::WriteProperty:
{
- Shiboken::GilState gil;
Shiboken::AutoDecRef value(converter.toPython(args[0]));
PySide::Property::setValue(pp, self, value);
break;
@@ -148,7 +146,6 @@ static void qpropertyMetaCall(PySideProperty *pp, PyObject *self, QMetaObject::C
case QMetaObject::ResetProperty:
{
- Shiboken::GilState gil;
PySide::Property::reset(pp, self);
break;
}
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index 845088367..1b5a0dee7 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -61,6 +61,7 @@
#include <algorithm>
#include <limits>
+#include <memory>
#if QSLOT_CODE != 1 || QSIGNAL_CODE != 2
#error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value!
@@ -72,7 +73,6 @@
namespace {
static PyObject *metaObjectAttr = nullptr;
- static int callMethod(QObject *object, int id, void **args);
static PyObject *parseArguments(const QList< QByteArray >& paramTypes, void **args);
static bool emitShortCircuitSignal(QObject *source, int signalIndex, PyObject *args);
@@ -225,6 +225,11 @@ struct SignalManager::SignalManagerPrivate
Q_ASSERT(m_globalReceivers->isEmpty());
}
}
+
+ static void handleMetaCallError(QObject *object, int *result);
+ static int qtPropertyMetacall(QObject *object, QMetaObject::Call call,
+ int id, void **args);
+ static int qtMethodMetacall(QObject *object, int id, void **args);
};
SignalManager::QmlMetaCallErrorHandler
@@ -362,87 +367,113 @@ bool SignalManager::emitSignal(QObject *source, const char *signal, PyObject *ar
return false;
}
-int SignalManager::qt_metacall(QObject *object, QMetaObject::Call call, int id, void **args)
+// Handle errors from meta calls. Requires GIL and PyErr_Occurred()
+void SignalManager::SignalManagerPrivate::handleMetaCallError(QObject *object, int *result)
+{
+ // Bubbles Python exceptions up to the Javascript engine, if called from one
+ if (m_qmlMetaCallErrorHandler) {
+ auto idOpt = m_qmlMetaCallErrorHandler(object);
+ if (idOpt.has_value())
+ *result = idOpt.value();
+ }
+
+ const int reclimit = Py_GetRecursionLimit();
+ // Inspired by Python's errors.c: PyErr_GivenExceptionMatches() function.
+ // Temporarily bump the recursion limit, so that PyErr_Print will not raise a recursion
+ // error again. Don't do it when the limit is already insanely high, to avoid overflow.
+ if (reclimit < (1 << 30))
+ Py_SetRecursionLimit(reclimit + 5);
+ PyErr_Print();
+ Py_SetRecursionLimit(reclimit);
+}
+
+// Handler for QMetaObject::ReadProperty/WriteProperty/ResetProperty:
+int SignalManager::SignalManagerPrivate::qtPropertyMetacall(QObject *object,
+ QMetaObject::Call call,
+ int id, void **args)
{
const QMetaObject *metaObject = object->metaObject();
- PySideProperty *pp = nullptr;
- PyObject *pp_name = nullptr;
- QMetaProperty mp;
- PyObject *pySelf = nullptr;
- int methodCount = metaObject->methodCount();
- int propertyCount = metaObject->propertyCount();
-
- if (call != QMetaObject::InvokeMetaMethod) {
- mp = metaObject->property(id);
- if (!mp.isValid()) {
- return id - methodCount;
- }
+ int result = id - metaObject->propertyCount();
- Shiboken::GilState gil;
- pySelf = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(object));
- Q_ASSERT(pySelf);
- pp_name = Shiboken::String::fromCString(mp.name());
- pp = Property::getObject(pySelf, pp_name);
- if (!pp) {
- qWarning("Invalid property: %s.", mp.name());
- Py_XDECREF(pp_name);
- return id - methodCount;
- }
+ const QMetaProperty mp = metaObject->property(id);
+ if (!mp.isValid())
+ return result;
+
+ Shiboken::GilState gil;
+ auto *pySbkSelf = Shiboken::BindingManager::instance().retrieveWrapper(object);
+ Q_ASSERT(pySbkSelf);
+ auto *pySelf = reinterpret_cast<PyObject *>(pySbkSelf);
+ Q_ASSERT(pySelf);
+ Shiboken::AutoDecRef pp_name(Shiboken::String::fromCString(mp.name()));
+ PySideProperty *pp = Property::getObject(pySelf, pp_name);
+ if (!pp) {
+ qWarning("Invalid property: %s.", mp.name());
+ return false;
}
+ pp->d->metaCallHandler(pp, pySelf, call, args);
+ Py_XDECREF(pp);
- switch(call) {
-#ifndef QT_NO_PROPERTIES
- case QMetaObject::ReadProperty:
- case QMetaObject::WriteProperty:
- case QMetaObject::ResetProperty:
- pp->d->metaCallHandler(pp, pySelf, call, args);
- break;
-#endif
- case QMetaObject::InvokeMetaMethod:
- id = callMethod(object, id, args);
- break;
+ if (PyErr_Occurred())
+ handleMetaCallError(object, &result);
+ return result;
+}
- default:
- qWarning("Unsupported meta invocation type.");
- }
+// Handler for QMetaObject::InvokeMetaMethod
+int SignalManager::SignalManagerPrivate::qtMethodMetacall(QObject *object,
+ int id, void **args)
+{
+ const QMetaObject *metaObject = object->metaObject();
+ const QMetaMethod method = metaObject->method(id);
+ int result = id - metaObject->methodCount();
- // WARNING Isn't safe to call any metaObject and/or object methods beyond this point
- // because the object can be deleted inside the called slot.
+ std::unique_ptr<Shiboken::GilState> gil;
- if (call == QMetaObject::InvokeMetaMethod) {
- id = id - methodCount;
+ if (method.methodType() == QMetaMethod::Signal) {
+ // emit python signal
+ QMetaObject::activate(object, id, args);
} else {
- id = id - propertyCount;
+ gil.reset(new Shiboken::GilState);
+ auto *pySbkSelf = Shiboken::BindingManager::instance().retrieveWrapper(object);
+ Q_ASSERT(pySbkSelf);
+ auto *pySelf = reinterpret_cast<PyObject *>(pySbkSelf);
+ QByteArray methodName = method.methodSignature();
+ methodName.truncate(methodName.indexOf('('));
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(pySelf, methodName));
+ SignalManager::callPythonMetaMethod(method, args, pyMethod, false);
}
+ // WARNING Isn't safe to call any metaObject and/or object methods beyond this point
+ // because the object can be deleted inside the called slot.
- if (pp || pp_name) {
- Shiboken::GilState gil;
- Py_XDECREF(pp);
- Py_XDECREF(pp_name);
- }
+ if (gil.get() == nullptr)
+ gil.reset(new Shiboken::GilState);
- {
- Shiboken::GilState gil;
-
- if (PyErr_Occurred()) {
- // Bubbles Python exceptions up to the Javascript engine, if called from one
- if (SignalManagerPrivate::m_qmlMetaCallErrorHandler) {
- auto idOpt = SignalManagerPrivate::m_qmlMetaCallErrorHandler(object);
- if (idOpt.has_value())
- return idOpt.value();
- }
+ if (PyErr_Occurred())
+ handleMetaCallError(object, &result);
- int reclimit = Py_GetRecursionLimit();
- // Inspired by Python's errors.c: PyErr_GivenExceptionMatches() function.
- // Temporarily bump the recursion limit, so that PyErr_Print will not raise a recursion
- // error again. Don't do it when the limit is already insanely high, to avoid overflow.
- if (reclimit < (1 << 30))
- Py_SetRecursionLimit(reclimit + 5);
- PyErr_Print();
- Py_SetRecursionLimit(reclimit);
- }
- }
+ return result;
+}
+int SignalManager::qt_metacall(QObject *object, QMetaObject::Call call, int id, void **args)
+{
+ switch (call) {
+ case QMetaObject::ReadProperty:
+ case QMetaObject::WriteProperty:
+ case QMetaObject::ResetProperty:
+ id = SignalManagerPrivate::qtPropertyMetacall(object, call, id, args);
+ break;
+ case QMetaObject::RegisterPropertyMetaType:
+ case QMetaObject::BindableProperty:
+ id -= object->metaObject()->propertyCount();
+ break;
+ case QMetaObject::InvokeMetaMethod:
+ id = SignalManagerPrivate::qtMethodMetacall(object, id, args);
+ break;
+ case QMetaObject::CreateInstance:
+ case QMetaObject::IndexOfMethod:
+ case QMetaObject::RegisterMethodArgumentMetaType:
+ id -= object->metaObject()->methodCount();
+ break;
+ }
return id;
}
@@ -565,26 +596,6 @@ const QMetaObject *SignalManager::retrieveMetaObject(PyObject *self)
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;
- auto self = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(object));
- QByteArray methodName = method.methodSignature();
- methodName.truncate(methodName.indexOf('('));
- Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(self, methodName));
- return SignalManager::callPythonMetaMethod(method, args, pyMethod, false);
- }
- return -1;
-}
-
-
static PyObject *parseArguments(const QList<QByteArray>& paramTypes, void **args)
{
int argsSize = paramTypes.count();