aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/PySide2/glue/qtcore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside2/PySide2/glue/qtcore.cpp')
-rw-r--r--sources/pyside2/PySide2/glue/qtcore.cpp478
1 files changed, 466 insertions, 12 deletions
diff --git a/sources/pyside2/PySide2/glue/qtcore.cpp b/sources/pyside2/PySide2/glue/qtcore.cpp
index 73b9476d1..47895bdda 100644
--- a/sources/pyside2/PySide2/glue/qtcore.cpp
+++ b/sources/pyside2/PySide2/glue/qtcore.cpp
@@ -75,7 +75,7 @@ static const char *QVariant_resolveMetaType(PyTypeObject *type, int *typeId)
}
// Do not resolve types to value type
if (valueType)
- return 0;
+ return nullptr;
// Find in base types. First check tp_bases, and only after check tp_base, because
// tp_base does not always point to the first base class, but rather to the first
// that has added any python fields or slots to its object layout.
@@ -93,7 +93,7 @@ static const char *QVariant_resolveMetaType(PyTypeObject *type, int *typeId)
}
}
*typeId = 0;
- return 0;
+ return nullptr;
}
static QVariant QVariant_convertToValueList(PyObject *list)
{
@@ -224,8 +224,8 @@ static QStack<PyObject*> globalPostRoutineFunctions;
void globalPostRoutineCallback()
{
Shiboken::GilState state;
- foreach (PyObject *callback, globalPostRoutineFunctions) {
- Shiboken::AutoDecRef result(PyObject_CallObject(callback, NULL));
+ for (auto *callback : globalPostRoutineFunctions) {
+ Shiboken::AutoDecRef result(PyObject_CallObject(callback, nullptr));
Py_DECREF(callback);
}
globalPostRoutineFunctions.clear();
@@ -259,6 +259,197 @@ PyModule_AddObject(module, "__version_info__", pyQtVersion);
PyModule_AddStringConstant(module, "__version__", qVersion());
// @snippet qt-version
+// @snippet qobject-connect
+static bool isDecorator(PyObject* method, PyObject* self)
+{
+ Shiboken::AutoDecRef methodName(PyObject_GetAttrString(method, "__name__"));
+ if (!PyObject_HasAttr(self, methodName))
+ return true;
+ Shiboken::AutoDecRef otherMethod(PyObject_GetAttr(self, methodName));
+ return PyMethod_GET_FUNCTION(otherMethod.object()) != PyMethod_GET_FUNCTION(method);
+}
+
+static bool getReceiver(QObject *source, const char* signal, PyObject* callback, QObject** receiver, PyObject** self, QByteArray* callbackSig)
+{
+ bool forceGlobalReceiver = false;
+ if (PyMethod_Check(callback)) {
+ *self = PyMethod_GET_SELF(callback);
+ if (%CHECKTYPE[QObject*](*self))
+ *receiver = %CONVERTTOCPP[QObject*](*self);
+ forceGlobalReceiver = isDecorator(callback, *self);
+ } else if (PyCFunction_Check(callback)) {
+ *self = PyCFunction_GET_SELF(callback);
+ if (*self && %CHECKTYPE[QObject*](*self))
+ *receiver = %CONVERTTOCPP[QObject*](*self);
+ } else if (PyCallable_Check(callback)) {
+ // Ok, just a callable object
+ *receiver = nullptr;
+ *self = nullptr;
+ }
+
+ bool usingGlobalReceiver = !*receiver || forceGlobalReceiver;
+
+ // Check if this callback is a overwrite of a non-virtual Qt slot.
+ if (!usingGlobalReceiver && receiver && self) {
+ *callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toLatin1();
+ const QMetaObject* metaObject = (*receiver)->metaObject();
+ int slotIndex = metaObject->indexOfSlot(callbackSig->constData());
+ if (slotIndex != -1 && slotIndex < metaObject->methodOffset() && PyMethod_Check(callback))
+ usingGlobalReceiver = true;
+ }
+
+ if (usingGlobalReceiver) {
+ PySide::SignalManager& signalManager = PySide::SignalManager::instance();
+ *receiver = signalManager.globalReceiver(source, callback);
+ *callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toLatin1();
+ }
+
+ return usingGlobalReceiver;
+}
+
+static bool qobjectConnect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type)
+{
+ if (!signal || !slot)
+ return false;
+
+ if (!PySide::Signal::checkQtSignal(signal))
+ return false;
+ signal++;
+
+ if (!PySide::SignalManager::registerMetaMethod(source, signal, QMetaMethod::Signal))
+ return false;
+
+ bool isSignal = PySide::Signal::isQtSignal(slot);
+ slot++;
+ PySide::SignalManager::registerMetaMethod(receiver, slot, isSignal ? QMetaMethod::Signal : QMetaMethod::Slot);
+ bool connection;
+ Py_BEGIN_ALLOW_THREADS
+ connection = QObject::connect(source, signal - 1, receiver, slot - 1, type);
+ Py_END_ALLOW_THREADS
+ return connection;
+}
+
+static bool qobjectConnect(QObject* source, QMetaMethod signal, QObject* receiver, QMetaMethod slot, Qt::ConnectionType type)
+{
+ return qobjectConnect(source, signal.methodSignature(), receiver, slot.methodSignature(), type);
+}
+
+static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject* callback, Qt::ConnectionType type)
+{
+ if (!signal || !PySide::Signal::checkQtSignal(signal))
+ return false;
+ signal++;
+
+ int signalIndex = PySide::SignalManager::registerMetaMethodGetIndex(source, signal, QMetaMethod::Signal);
+ if (signalIndex == -1)
+ return false;
+
+ PySide::SignalManager& signalManager = PySide::SignalManager::instance();
+
+ // Extract receiver from callback
+ QObject* receiver = nullptr;
+ PyObject* self = nullptr;
+ QByteArray callbackSig;
+ bool usingGlobalReceiver = getReceiver(source, signal, callback, &receiver, &self, &callbackSig);
+ if (receiver == nullptr && self == nullptr)
+ return false;
+
+ const QMetaObject* metaObject = receiver->metaObject();
+ const char* slot = callbackSig.constData();
+ int slotIndex = metaObject->indexOfSlot(slot);
+ QMetaMethod signalMethod = metaObject->method(signalIndex);
+
+ if (slotIndex == -1) {
+ if (!usingGlobalReceiver && self && !Shiboken::Object::hasCppWrapper((SbkObject*)self)) {
+ qWarning("You can't add dynamic slots on an object originated from C++.");
+ if (usingGlobalReceiver)
+ signalManager.releaseGlobalReceiver(source, receiver);
+
+ return false;
+ }
+
+ if (usingGlobalReceiver)
+ slotIndex = signalManager.globalReceiverSlotIndex(receiver, slot);
+ else
+ slotIndex = PySide::SignalManager::registerMetaMethodGetIndex(receiver, slot, QMetaMethod::Slot);
+
+ if (slotIndex == -1) {
+ if (usingGlobalReceiver)
+ signalManager.releaseGlobalReceiver(source, receiver);
+
+ return false;
+ }
+ }
+ bool connection;
+ Py_BEGIN_ALLOW_THREADS
+ connection = QMetaObject::connect(source, signalIndex, receiver, slotIndex, type);
+ Py_END_ALLOW_THREADS
+ if (connection) {
+ if (usingGlobalReceiver)
+ signalManager.notifyGlobalReceiver(receiver);
+ #ifndef AVOID_PROTECTED_HACK
+ source->connectNotify(signalMethod); //Qt5: QMetaMethod instead of char*
+ #else
+ // Need to cast to QObjectWrapper* and call the public version of
+ // connectNotify when avoiding the protected hack.
+ reinterpret_cast<QObjectWrapper*>(source)->connectNotify(signalMethod); //Qt5: QMetaMethod instead of char*
+ #endif
+
+ return connection;
+ }
+
+ if (usingGlobalReceiver)
+ signalManager.releaseGlobalReceiver(source, receiver);
+
+ return false;
+}
+
+
+static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObject* callback)
+{
+ if (!PySide::Signal::checkQtSignal(signal))
+ return false;
+
+ PySide::SignalManager& signalManager = PySide::SignalManager::instance();
+
+ // Extract receiver from callback
+ QObject* receiver = nullptr;
+ PyObject* self = nullptr;
+ QByteArray callbackSig;
+ QMetaMethod slotMethod;
+ bool usingGlobalReceiver = getReceiver(nullptr, signal, callback, &receiver, &self, &callbackSig);
+ if (receiver == nullptr && self == nullptr)
+ return false;
+
+ const QMetaObject* metaObject = receiver->metaObject();
+ int signalIndex = source->metaObject()->indexOfSignal(++signal);
+ int slotIndex = -1;
+
+ slotIndex = metaObject->indexOfSlot(callbackSig);
+ slotMethod = metaObject->method(slotIndex);
+
+ bool disconnected;
+ Py_BEGIN_ALLOW_THREADS
+ disconnected = QMetaObject::disconnectOne(source, signalIndex, receiver, slotIndex);
+ Py_END_ALLOW_THREADS
+
+ if (disconnected) {
+ if (usingGlobalReceiver)
+ signalManager.releaseGlobalReceiver(source, receiver);
+
+ #ifndef AVOID_PROTECTED_HACK
+ source->disconnectNotify(slotMethod); //Qt5: QMetaMethod instead of char*
+ #else
+ // Need to cast to QObjectWrapper* and call the public version of
+ // connectNotify when avoiding the protected hack.
+ reinterpret_cast<QObjectWrapper*>(source)->disconnectNotify(slotMethod); //Qt5: QMetaMethod instead of char*
+ #endif
+ return true;
+ }
+ return false;
+}
+// @snippet qobject-connect
+
// @snippet qobject-connect-1
// %FUNCTION_NAME() - disable generation of function call.
bool %0 = qobjectConnect(%1, %2, %CPPSELF, %3, %4);
@@ -514,10 +705,51 @@ qRegisterMetaType<QVector<int> >("QVector<int>");
%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
// @snippet qobject-metaobject
-// @snippet qobject-findchild
+// @snippet qobject-findchild-1
+static QObject* _findChildHelper(const QObject* parent, const QString& name, PyTypeObject* desiredType)
+{
+ for (auto *child : parent->children()) {
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject*](child));
+ if (PyType_IsSubtype(Py_TYPE(pyChild), desiredType)
+ && (name.isNull() || name == child->objectName())) {
+ return child;
+ }
+ }
+
+ for (auto *child : parent->children()) {
+ QObject *obj = _findChildHelper(child, name, desiredType);
+ if (obj)
+ return obj;
+ }
+ return nullptr;
+}
+
+static inline bool _findChildrenComparator(const QObject*& child, const QRegExp& name)
+{
+ return name.indexIn(child->objectName()) != -1;
+}
+
+static inline bool _findChildrenComparator(const QObject*& child, const QString& name)
+{
+ return name.isNull() || name == child->objectName();
+}
+
+template<typename T>
+static void _findChildrenHelper(const QObject* parent, const T& name, PyTypeObject* desiredType, PyObject* result)
+{
+ for (const auto *child : parent->children()) {
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject*](child));
+ if (PyType_IsSubtype(Py_TYPE(pyChild), desiredType) && _findChildrenComparator(child, name))
+ PyList_Append(result, pyChild);
+ _findChildrenHelper(child, name, desiredType, result);
+ }
+}
+// @snippet qobject-findchild-1
+
+// @snippet qobject-findchild-2
QObject *child = _findChildHelper(%CPPSELF, %2, (PyTypeObject*)%PYARG_1);
%PYARG_0 = %CONVERTTOPYTHON[QObject*](child);
-// @snippet qobject-findchild
+// @snippet qobject-findchild-2
// @snippet qobject-findchildren-1
%PYARG_0 = PyList_New(0);
@@ -560,6 +792,214 @@ if (ret > 0 && ((strcmp(%1, SIGNAL(destroyed())) == 0) || (strcmp(%1, SIGNAL(des
%PYARG_0 = %CONVERTTOPYTHON[QString](%1);
// @snippet qregexp-replace
+// @snippet qbytearray-mgetitem
+if (PyIndex_Check(_key)) {
+ Py_ssize_t _i;
+ _i = PyNumber_AsSsize_t(_key, PyExc_IndexError);
+ if (_i < 0 || _i >= %CPPSELF.size()) {
+ PyErr_SetString(PyExc_IndexError, "index out of bounds");
+ return 0;
+ } else {
+ char res[2];
+ res[0] = %CPPSELF.at(_i);
+ res[1] = 0;
+ return PyBytes_FromStringAndSize(res, 1);
+ }
+} else if (PySlice_Check(_key)) {
+ Py_ssize_t start, stop, step, slicelength, cur;
+
+#ifdef IS_PY3K
+ PyObject *key = _key;
+#else
+ PySliceObject *key = reinterpret_cast<PySliceObject *>(_key);
+#endif
+ if (PySlice_GetIndicesEx(key, %CPPSELF.count(), &start, &stop, &step, &slicelength) < 0) {
+ return nullptr;
+ }
+
+ QByteArray ba;
+ if (slicelength <= 0) {
+ return %CONVERTTOPYTHON[QByteArray](ba);
+ } else if (step == 1) {
+ Py_ssize_t max = %CPPSELF.count();
+ start = qBound(Py_ssize_t(0), start, max);
+ stop = qBound(Py_ssize_t(0), stop, max);
+ QByteArray ba;
+ if (start < stop)
+ ba = %CPPSELF.mid(start, stop - start);
+ return %CONVERTTOPYTHON[QByteArray](ba);
+ } else {
+ QByteArray ba;
+ for (cur = start; slicelength > 0; cur += static_cast<size_t>(step), slicelength--) {
+ ba.append(%CPPSELF.at(cur));
+ }
+ return %CONVERTTOPYTHON[QByteArray](ba);
+ }
+} else {
+ PyErr_Format(PyExc_TypeError,
+ "list indices must be integers or slices, not %.200s",
+ Py_TYPE(_key)->tp_name);
+ return nullptr;
+}
+// @snippet qbytearray-mgetitem
+
+// @snippet qbytearray-msetitem
+if (PyIndex_Check(_key)) {
+ Py_ssize_t _i = PyNumber_AsSsize_t(_key, PyExc_IndexError);
+ if (_i == -1 && PyErr_Occurred())
+ return -1;
+
+ if (_i < 0)
+ _i += %CPPSELF.count();
+
+ if (_i < 0 || _i >= %CPPSELF.size()) {
+ PyErr_SetString(PyExc_IndexError, "QByteArray index out of range");
+ return -1;
+ }
+
+ // Provide more specific error message for bytes/str, bytearray, QByteArray respectively
+#ifdef IS_PY3K
+ if (PyBytes_Check(_value)) {
+ if (Py_SIZE(_value) != 1) {
+ PyErr_SetString(PyExc_ValueError, "bytes must be of size 1");
+#else
+ if (PyString_CheckExact(_value)) {
+ if (Py_SIZE(_value) != 1) {
+ PyErr_SetString(PyExc_ValueError, "str must be of size 1");
+#endif
+ return -1;
+ }
+ } else if (PyByteArray_Check(_value)) {
+ if (Py_SIZE(_value) != 1) {
+ PyErr_SetString(PyExc_ValueError, "bytearray must be of size 1");
+ return -1;
+ }
+ } else if (reinterpret_cast<PyTypeObject *>(Py_TYPE(_value)) == reinterpret_cast<PyTypeObject *>(SbkPySide2_QtCoreTypes[SBK_QBYTEARRAY_IDX])) {
+ if (PyObject_Length(_value) != 1) {
+ PyErr_SetString(PyExc_ValueError, "QByteArray must be of size 1");
+ return -1;
+ }
+ } else {
+#ifdef IS_PY3K
+ PyErr_SetString(PyExc_ValueError, "a bytes, bytearray, QByteArray of size 1 is required");
+#else
+ PyErr_SetString(PyExc_ValueError, "a str, bytearray, QByteArray of size 1 is required");
+#endif
+ return -1;
+ }
+
+ // Not support int or long.
+ %CPPSELF.remove(_i, 1);
+ PyObject *args = Py_BuildValue("(nO)", _i, _value);
+ PyObject *result = Sbk_QByteArrayFunc_insert(self, args);
+ Py_DECREF(args);
+ Py_XDECREF(result);
+ return !result ? -1 : 0;
+} else if (PySlice_Check(_key)) {
+ Py_ssize_t start, stop, step, slicelength, value_length;
+
+#ifdef IS_PY3K
+ PyObject *key = _key;
+#else
+ PySliceObject *key = reinterpret_cast<PySliceObject *>(_key);
+#endif
+ if (PySlice_GetIndicesEx(key, %CPPSELF.count(), &start, &stop, &step, &slicelength) < 0) {
+ return -1;
+ }
+ // The parameter candidates are: bytes/str, bytearray, QByteArray itself.
+ // Not support iterable which contains ints between 0~255
+
+ // case 1: value is nullpre, means delete the items within the range
+ // case 2: step is 1, means shrink or expanse
+ // case 3: step is not 1, then the number of slots have to equal the number of items in _value
+ QByteArray ba;
+ if (_value == nullptr || _value == Py_None) {
+ ba = QByteArray();
+ value_length = 0;
+ } else if (!(PyBytes_Check(_value) || PyByteArray_Check(_value) || reinterpret_cast<PyTypeObject *>(Py_TYPE(_value)) == reinterpret_cast<PyTypeObject *>(SbkPySide2_QtCoreTypes[SBK_QBYTEARRAY_IDX]))) {
+ PyErr_Format(PyExc_TypeError, "bytes, bytearray or QByteArray is required, not %.200s", Py_TYPE(_value)->tp_name);
+ return -1;
+ } else {
+ value_length = PyObject_Length(_value);
+ }
+
+ if (step != 1 && value_length != slicelength) {
+ PyErr_Format(PyExc_ValueError, "attempt to assign %s of size %d to extended slice of size %d",Py_TYPE(_value)->tp_name, value_length, slicelength);
+ return -1;
+ }
+
+ if (step != 1) {
+ int i = start;
+ for (int j = 0; j < slicelength; j++) {
+ PyObject *item = PyObject_GetItem(_value, PyLong_FromLong(j));
+ QByteArray temp;
+#ifdef IS_PY3K
+ if (PyLong_Check(item)) {
+#else
+ if (PyLong_Check(item) || PyInt_Check(item)) {
+#endif
+ int overflow;
+ long ival = PyLong_AsLongAndOverflow(item, &overflow);
+ // Not suppose to bigger than 255 because only bytes, bytearray, QByteArray were accept
+ const char *el = reinterpret_cast<const char*>(&ival);
+ temp = QByteArray(el);
+ } else {
+ temp = %CONVERTTOCPP[QByteArray](item);
+ }
+
+ %CPPSELF.replace(i, 1, temp);
+ i += step;
+ }
+ return 0;
+ } else {
+ ba = %CONVERTTOCPP[QByteArray](_value);
+ %CPPSELF.replace(start, slicelength, ba);
+ return 0;
+ }
+} else {
+ PyErr_Format(PyExc_TypeError, "QBytearray indices must be integers or slices, not %.200s",
+ Py_TYPE(_key)->tp_name);
+ return -1;
+}
+// @snippet qbytearray-msetitem
+
+// @snippet qbytearray-bufferprotocol
+#if PY_VERSION_HEX < 0x03000000
+
+// QByteArray buffer protocol functions
+// see: http://www.python.org/dev/peps/pep-3118/
+
+extern "C" {
+
+static Py_ssize_t SbkQByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp)
+{
+ if (lenp)
+ *lenp = Py_TYPE(self)->tp_as_sequence->sq_length(self);
+ return 1;
+}
+
+static Py_ssize_t SbkQByteArray_readbufferproc(PyObject* self, Py_ssize_t segment, void** ptrptr)
+{
+ if (segment || !Shiboken::Object::isValid(self))
+ return -1;
+
+ QByteArray* cppSelf = %CONVERTTOCPP[QByteArray*](self);
+ *ptrptr = reinterpret_cast<void*>(cppSelf->data());
+ return cppSelf->size();
+}
+
+PyBufferProcs SbkQByteArrayBufferProc = {
+ /*bf_getreadbuffer*/ &SbkQByteArray_readbufferproc,
+ /*bf_getwritebuffer*/ (writebufferproc) &SbkQByteArray_readbufferproc,
+ /*bf_getsegcount*/ &SbkQByteArray_segcountproc,
+ /*bf_getcharbuffer*/ (charbufferproc) &SbkQByteArray_readbufferproc
+};
+
+}
+
+#endif
+// @snippet qbytearray-bufferprotocol
+
// @snippet qbytearray-operatorplus-1
QByteArray ba = QByteArray(PyBytes_AS_STRING(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1)) + *%CPPSELF;
%PYARG_0 = %CONVERTTOPYTHON[QByteArray](ba);
@@ -635,8 +1075,8 @@ if (PyUnicode_CheckExact(%PYARG_1)) {
// @snippet qbytearray-repr
PyObject *aux = PyBytes_FromStringAndSize(%CPPSELF.constData(), %CPPSELF.size());
-if (aux == NULL) {
- return NULL;
+if (aux == nullptr) {
+ return nullptr;
}
QByteArray b(Py_TYPE(%PYSELF)->tp_name);
#ifdef IS_PY3K
@@ -685,8 +1125,8 @@ if (PyBytes_Check(%PYARG_1)) {
// @snippet qbytearray-str
PyObject *aux = PyBytes_FromStringAndSize(%CPPSELF.constData(), %CPPSELF.size());
-if (aux == NULL) {
- return NULL;
+if (aux == nullptr) {
+ return nullptr;
}
#ifdef IS_PY3K
%PYARG_0 = PyObject_Repr(aux);
@@ -845,6 +1285,20 @@ long result;
%PYARG_0 = %CONVERTTOPYTHON[long](result);
// @snippet qprocess-pid
+// @snippet qcoreapplication-init
+static void QCoreApplicationConstructor(PyObject *self, PyObject *pyargv, QCoreApplicationWrapper **cptr)
+{
+ static int argc;
+ static char **argv;
+ PyObject *stringlist = PyTuple_GET_ITEM(pyargv, 0);
+ if (Shiboken::listToArgcArgv(stringlist, &argc, &argv, "PySideApp")) {
+ *cptr = new QCoreApplicationWrapper(argc, argv);
+ Shiboken::Object::releaseOwnership(reinterpret_cast<SbkObject*>(self));
+ PySide::registerCleanupFunction(&PySide::destroyQCoreApplication);
+ }
+}
+// @snippet qcoreapplication-init
+
// @snippet qcoreapplication-1
QCoreApplicationConstructor(%PYSELF, args, &%0);
// @snippet qcoreapplication-1
@@ -959,7 +1413,7 @@ QSignalTransition *%0 = %CPPSELF->%FUNCTION_NAME(sender, PySide::Signal::getSign
// @snippet qstatemachine-configuration
%PYARG_0 = PySet_New(0);
-foreach (QAbstractState *abs_state, %CPPSELF.configuration()) {
+for (auto *abs_state : %CPPSELF.configuration()) {
Shiboken::AutoDecRef obj(%CONVERTTOPYTHON[QAbstractState*](abs_state));
Shiboken::Object::setParent(self, obj);
PySet_Add(%PYARG_0, obj);
@@ -968,7 +1422,7 @@ foreach (QAbstractState *abs_state, %CPPSELF.configuration()) {
// @snippet qstatemachine-defaultanimations
%PYARG_0 = PyList_New(0);
-foreach (QAbstractAnimation *abs_anim, %CPPSELF.defaultAnimations()) {
+for (auto *abs_anim : %CPPSELF.defaultAnimations()) {
Shiboken::AutoDecRef obj(%CONVERTTOPYTHON[QAbstractAnimation*](abs_anim));
Shiboken::Object::setParent(self, obj);
PyList_Append(%PYARG_0, obj);