aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/PySide2/glue
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside2/PySide2/glue')
-rw-r--r--sources/pyside2/PySide2/glue/qtcore.cpp478
-rw-r--r--sources/pyside2/PySide2/glue/qtgui.cpp16
-rw-r--r--sources/pyside2/PySide2/glue/qtuitools.cpp53
-rw-r--r--sources/pyside2/PySide2/glue/qtwidgets.cpp275
4 files changed, 801 insertions, 21 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);
diff --git a/sources/pyside2/PySide2/glue/qtgui.cpp b/sources/pyside2/PySide2/glue/qtgui.cpp
index 759d0a85a..a34bcff43 100644
--- a/sources/pyside2/PySide2/glue/qtgui.cpp
+++ b/sources/pyside2/PySide2/glue/qtgui.cpp
@@ -117,7 +117,7 @@ if (doc) {
// @snippet qpolygon-reduce
PyObject *points = PyList_New(%CPPSELF.count());
-for (int i = 0, max = %CPPSELF.count(); i < max; ++i){
+for (int i = 0, i_max = %CPPSELF.count(); i < i_max; ++i){
int x, y;
%CPPSELF.point(i, &x, &y);
QPoint pt = QPoint(x, y);
@@ -485,6 +485,20 @@ PyErr_SetString(PyExc_IndexError, "Invalid matrix index.");
return 0;
// @snippet qmatrix4x4-mgetitem
+// @snippet qguiapplication-init
+static void QGuiApplicationConstructor(PyObject *self, PyObject *pyargv, QGuiApplicationWrapper **cptr)
+{
+ static int argc;
+ static char **argv;
+ PyObject *stringlist = PyTuple_GET_ITEM(pyargv, 0);
+ if (Shiboken::listToArgcArgv(stringlist, &argc, &argv, "PySideApp")) {
+ *cptr = new QGuiApplicationWrapper(argc, argv, 0);
+ Shiboken::Object::releaseOwnership(reinterpret_cast<SbkObject*>(self));
+ PySide::registerCleanupFunction(&PySide::destroyQCoreApplication);
+ }
+}
+// @snippet qguiapplication-init
+
// @snippet qguiapplication-1
QGuiApplicationConstructor(%PYSELF, args, &%0);
// @snippet qguiapplication-1
diff --git a/sources/pyside2/PySide2/glue/qtuitools.cpp b/sources/pyside2/PySide2/glue/qtuitools.cpp
index 0a2feb262..d0469e97d 100644
--- a/sources/pyside2/PySide2/glue/qtuitools.cpp
+++ b/sources/pyside2/PySide2/glue/qtuitools.cpp
@@ -36,6 +36,59 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+// @snippet uitools-loadui
+/*
+ * Based on code provided by:
+ * Antonio Valentino <antonio.valentino at tiscali.it>
+ * Frédéric <frederic.mantegazza at gbiloba.org>
+ */
+
+#include <shiboken.h>
+#include <QUiLoader>
+#include <QFile>
+#include <QWidget>
+
+static void createChildrenNameAttributes(PyObject* root, QObject* object)
+{
+ for (auto *child : object->children()) {
+ const QByteArray name = child->objectName().toLocal8Bit();
+
+ if (!name.isEmpty() && !name.startsWith("_") && !name.startsWith("qt_")) {
+ if (!PyObject_HasAttrString(root, name.constData())) {
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject*](child));
+ PyObject_SetAttrString(root, name.constData(), pyChild);
+ }
+ createChildrenNameAttributes(root, child);
+ }
+ createChildrenNameAttributes(root, child);
+ }
+}
+
+static PyObject* QUiLoadedLoadUiFromDevice(QUiLoader* self, QIODevice* dev, QWidget* parent)
+{
+ QWidget* wdg = self->load(dev, parent);
+
+ if (wdg) {
+ PyObject* pyWdg = %CONVERTTOPYTHON[QWidget*](wdg);
+ createChildrenNameAttributes(pyWdg, wdg);
+ if (parent) {
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget*](parent));
+ Shiboken::Object::setParent(pyParent, pyWdg);
+ }
+ return pyWdg;
+ }
+
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Unable to open/read ui device");
+ return nullptr;
+}
+
+static PyObject* QUiLoaderLoadUiFromFileName(QUiLoader* self, const QString& uiFile, QWidget* parent)
+{
+ QFile fd(uiFile);
+ return QUiLoadedLoadUiFromDevice(self, &fd, parent);
+}
+// @snippet uitools-loadui
// @snippet quiloader
Q_IMPORT_PLUGIN(PyCustomWidgets);
diff --git a/sources/pyside2/PySide2/glue/qtwidgets.cpp b/sources/pyside2/PySide2/glue/qtwidgets.cpp
index 7ec0ca266..b44be183d 100644
--- a/sources/pyside2/PySide2/glue/qtwidgets.cpp
+++ b/sources/pyside2/PySide2/glue/qtwidgets.cpp
@@ -110,6 +110,34 @@ PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](retval_));
PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%ARG5_TYPE](%5));
// @snippet qfiledialog-return
+// @snippet qmenu-glue
+inline PyObject* addActionWithPyObject(QMenu* self, const QIcon& icon, const QString& text, PyObject* callback, const QKeySequence& shortcut)
+{
+ QAction* act = self->addAction(text);
+
+ if (!icon.isNull())
+ act->setIcon(icon);
+
+ if (!shortcut.isEmpty())
+ act->setShortcut(shortcut);
+
+ self->addAction(act);
+
+ PyObject* pyAct = %CONVERTTOPYTHON[QAction*](act);
+ Shiboken::AutoDecRef result(PyObject_CallMethod(pyAct,
+ const_cast<char *>("connect"),
+ const_cast<char *>("OsO"),
+ pyAct,
+ SIGNAL(triggered()), callback));
+ if (result.isNull()) {
+ Py_DECREF(pyAct);
+ return nullptr;
+ }
+
+ return pyAct;
+}
+// @snippet qmenu-glue
+
// @snippet qmenu-addaction-1
%PYARG_0 = addActionWithPyObject(%CPPSELF, QIcon(), %1, %2, %3);
// @snippet qmenu-addaction-1
@@ -125,7 +153,7 @@ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%ARG5_TYPE](%5));
// @snippet qmenu-clear
Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
const auto &actions = %CPPSELF.actions();
-for (QAction *act : actions) {
+for (auto *act : actions) {
if (auto wrapper = bm.retrieveWrapper(act)) {
auto pyObj = reinterpret_cast<PyObject *>(wrapper);
Py_INCREF(pyObj);
@@ -136,9 +164,35 @@ for (QAction *act : actions) {
}
// @snippet qmenu-clear
+// @snippet qmenubar-glue
+inline PyObject*
+addActionWithPyObject(QMenuBar* self, const QString& text, PyObject* callback)
+{
+ QAction* act = self->addAction(text);
+
+ self->addAction(act);
+
+ PyObject* pyAct = %CONVERTTOPYTHON[QAction*](act);
+ PyObject* result = PyObject_CallMethod(pyAct,
+ const_cast<char *>("connect"),
+ const_cast<char *>("OsO"),
+ pyAct,
+ SIGNAL(triggered(bool)), callback);
+
+ if (result == nullptr || result == Py_False) {
+ if (result)
+ Py_DECREF(result);
+ Py_DECREF(pyAct);
+ return nullptr;
+ }
+
+ return pyAct;
+}
+// @snippet qmenubar-glue
+
// @snippet qmenubar-clear
const auto &actions = %CPPSELF.actions();
-for (QAction *act : actions) {
+for (auto *act : actions) {
Shiboken::AutoDecRef pyAct(%CONVERTTOPYTHON[QAction*](act));
Shiboken::Object::setParent(NULL, pyAct);
Shiboken::Object::invalidate(pyAct);
@@ -175,6 +229,131 @@ if (_widget) {
}
// @snippet qtoolbox-removeitem
+// @snippet qlayout-help-functions
+void addLayoutOwnership(QLayout* layout, QLayoutItem* item);
+void removeLayoutOwnership(QLayout* layout, QWidget* widget);
+
+inline QByteArray retrieveObjectName(PyObject* obj)
+{
+ Shiboken::AutoDecRef objName(PyObject_Str(obj));
+ return Shiboken::String::toCString(objName);
+}
+
+inline void addLayoutOwnership(QLayout* layout, QWidget* widget)
+{
+ //transfer ownership to parent widget
+ QWidget *lw = layout->parentWidget();
+ QWidget *pw = widget->parentWidget();
+
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QWidget*](widget));
+
+ //Transfer parent to layout widget
+ if (pw && lw && pw != lw)
+ Shiboken::Object::setParent(0, pyChild);
+
+ if (!lw && !pw) {
+ //keep the reference while the layout is orphan
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget*](layout));
+ Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(pyParent.object()), retrieveObjectName(pyParent).data(), pyChild, true);
+ } else {
+ if (!lw)
+ lw = pw;
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget*](lw));
+ Shiboken::Object::setParent(pyParent, pyChild);
+ }
+}
+
+inline void addLayoutOwnership(QLayout* layout, QLayout* other)
+{
+ //transfer all children widgets from other to layout parent widget
+ QWidget* parent = layout->parentWidget();
+ if (!parent) {
+ //keep the reference while the layout is orphan
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QLayout*](layout));
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QLayout*](other));
+ Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(pyParent.object()), retrieveObjectName(pyParent).data(), pyChild, true);
+ return;
+ }
+
+ for (int i=0, i_max=other->count(); i < i_max; i++) {
+ QLayoutItem* item = other->itemAt(i);
+ if (PyErr_Occurred() || !item)
+ return;
+ addLayoutOwnership(layout, item);
+ }
+
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QLayout*](layout));
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QLayout*](other));
+ Shiboken::Object::setParent(pyParent, pyChild);
+}
+
+inline void addLayoutOwnership(QLayout* layout, QLayoutItem* item)
+{
+ if (!item)
+ return;
+
+ QWidget* w = item->widget();
+ if (w)
+ addLayoutOwnership(layout, w);
+ else {
+ QLayout* l = item->layout();
+ if (l)
+ addLayoutOwnership(layout, l);
+ }
+
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QLayout*](layout));
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QLayoutItem*](item));
+ Shiboken::Object::setParent(pyParent, pyChild);
+}
+
+static void removeWidgetFromLayout(QLayout* layout, QWidget* widget)
+{
+ QWidget* parent = widget->parentWidget();
+
+ if (!parent) {
+ //remove reference on layout
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget*](layout));
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QWidget*](widget));
+ Shiboken::Object::removeReference(reinterpret_cast<SbkObject*>(pyParent.object()), retrieveObjectName(pyParent).data(), pyChild);
+ } else {
+ //give the ownership to parent
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget*](parent));
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QWidget*](widget));
+ Shiboken::Object::setParent(pyParent, pyChild);
+ }
+}
+
+inline void removeLayoutOwnership(QLayout* layout, QLayoutItem* item)
+{
+ QWidget* w = item->widget();
+ if (w)
+ removeWidgetFromLayout(layout, w);
+ else {
+ QLayout* l = item->layout();
+ if (l && item != l)
+ removeLayoutOwnership(layout, l);
+ }
+
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QLayoutItem*](item));
+ Shiboken::Object::invalidate(pyChild);
+ Shiboken::Object::setParent(0, pyChild);
+}
+
+inline void removeLayoutOwnership(QLayout* layout, QWidget* widget)
+{
+ if (!widget)
+ return;
+
+ for (int i=0, i_max=layout->count(); i < i_max; i++) {
+ QLayoutItem* item = layout->itemAt(i);
+ if (PyErr_Occurred() || !item)
+ return;
+ if (item->widget() == widget)
+ removeLayoutOwnership(layout, item);
+ }
+}
+// @snippet qlayout-help-functions
+
// @snippet qlayout-setalignment
%CPPSELF.setAlignment(%1);
// @snippet qlayout-setalignment
@@ -209,7 +388,7 @@ PyTuple_SET_ITEM(%PYARG_0, 3, %CONVERTTOPYTHON[int](d));
QGraphicsItem* parentItem = %1->parentItem();
Shiboken::AutoDecRef parent(%CONVERTTOPYTHON[QGraphicsItem*](parentItem));
const auto &childItems = %1->childItems();
-for (QGraphicsItem *item : childItems)
+for (auto *item : childItems)
Shiboken::Object::setParent(parent, %CONVERTTOPYTHON[QGraphicsItem*](item));
%BEGIN_ALLOW_THREADS
%CPPSELF.%FUNCTION_NAME(%1);
@@ -227,7 +406,7 @@ Shiboken::Object::keepReference((SbkObject*)%PYARG_0, "setWidget(QWidget*)1", %P
// @snippet qgraphicsscene-clear
const QList<QGraphicsItem*> items = %CPPSELF.items();
Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
-for (QGraphicsItem *item : items) {
+for (auto *item : items) {
SbkObject* obj = bm.retrieveWrapper(item);
if (obj) {
if (reinterpret_cast<PyObject*>(obj)->ob_refcnt > 1) // If the refcnt is 1 the object will vannish anyway.
@@ -241,7 +420,7 @@ for (QGraphicsItem *item : items) {
// @snippet qtreewidget-clear
QTreeWidgetItem *rootItem = %CPPSELF.invisibleRootItem();
Shiboken::BindingManager &bm = Shiboken::BindingManager::instance();
-for (int i = 0; i < rootItem->childCount(); ++i) {
+for (int i = 0, i_count = rootItem->childCount(); i < i_count; ++i) {
QTreeWidgetItem *item = rootItem->child(i);
SbkObject* wrapper = bm.retrieveWrapper(item);
if (wrapper)
@@ -271,6 +450,72 @@ for (int i = 0, count = %CPPSELF.count(); i < count; ++i) {
%CPPSELF.%FUNCTION_NAME();
// @snippet qlistwidget-clear
+// @snippet qwidget-glue
+static QString retrieveObjectName(PyObject *obj)
+{
+ Shiboken::AutoDecRef objName(PyObject_Str(obj));
+ return QString(Shiboken::String::toCString(objName));
+}
+
+
+// Transfer objects ownership from layout to widget
+static inline void qwidgetReparentLayout(QWidget *parent, QLayout *layout)
+{
+ Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget*](parent));
+
+ for (int i=0, i_count = layout->count(); i < i_count; i++) {
+ QLayoutItem* item = layout->itemAt(i);
+ if (PyErr_Occurred() || !item)
+ return;
+
+ QWidget* w = item->widget();
+ if (w) {
+ QWidget* pw = w->parentWidget();
+ if (pw != parent) {
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QWidget*](w));
+ Shiboken::Object::setParent(pyParent, pyChild);
+ }
+ } else {
+ QLayout* l = item->layout();
+ if (l)
+ qwidgetReparentLayout(parent, l);
+ }
+ }
+
+ Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QLayout*](layout));
+ Shiboken::Object::setParent(pyParent, pyChild);
+ //remove previous references
+ Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(pyChild.object()), qPrintable(retrieveObjectName(pyChild)), Py_None);
+}
+
+static inline void qwidgetSetLayout(QWidget *self, QLayout *layout)
+{
+ if (!layout || self->layout())
+ return;
+
+ QObject* oldParent = layout->parent();
+ if (oldParent && oldParent != self) {
+ if (oldParent->isWidgetType()) {
+ // remove old parent policy
+ Shiboken::AutoDecRef pyLayout(%CONVERTTOPYTHON[QLayout*](layout));
+ Shiboken::Object::setParent(Py_None, pyLayout);
+ } else {
+ PyErr_Format(PyExc_RuntimeError, "QWidget::setLayout: Attempting to set QLayout \"%s\" on %s \"%s\", when the QLayout already has a parent",
+ qPrintable(layout->objectName()), self->metaObject()->className(), qPrintable(self->objectName()));
+ return;
+ }
+ }
+
+ if (oldParent != self) {
+ qwidgetReparentLayout(self, layout);
+ if (PyErr_Occurred())
+ return;
+
+ self->setLayout(layout);
+ }
+}
+// @snippet qwidget-glue
+
// @snippet qwidget-setstyle
Shiboken::Object::keepReference(reinterpret_cast<SbkObject*>(%PYSELF), "__style__", %PYARG_1);
// @snippet qwidget-setstyle
@@ -290,6 +535,20 @@ if (myStyle && qApp) {
}
// @snippet qwidget-style
+// @snippet qapplication-init
+static void QApplicationConstructor(PyObject *self, PyObject *pyargv, QApplicationWrapper **cptr)
+{
+ static int argc;
+ static char **argv;
+ PyObject *stringlist = PyTuple_GET_ITEM(pyargv, 0);
+ if (Shiboken::listToArgcArgv(stringlist, &argc, &argv, "PySideApp")) {
+ *cptr = new QApplicationWrapper(argc, argv, 0);
+ Shiboken::Object::releaseOwnership(reinterpret_cast<SbkObject*>(self));
+ PySide::registerCleanupFunction(&PySide::destroyQCoreApplication);
+ }
+}
+// @snippet qapplication-init
+
// @snippet qapplication-setStyle
if (qApp) {
Shiboken::AutoDecRef pyApp(%CONVERTTOPYTHON[QApplication*](qApp));
@@ -355,7 +614,7 @@ Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0,
QList<PyObject* > lst;
Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();
const auto &toolButtonChildren = %CPPSELF.findChildren<QToolButton*>();
-for (QToolButton *child : toolButtonChildren) {
+for (auto *child : toolButtonChildren) {
if (bm.hasWrapper(child)) {
PyObject* pyChild = %CONVERTTOPYTHON[QToolButton*](child);
Shiboken::Object::setParent(0, pyChild);
@@ -365,14 +624,14 @@ for (QToolButton *child : toolButtonChildren) {
//Remove actions
const auto &actions = %CPPSELF.actions();
-for (QAction *act : actions) {
+for (auto *act : actions) {
Shiboken::AutoDecRef pyAct(%CONVERTTOPYTHON[QAction*](act));
Shiboken::Object::setParent(NULL, pyAct);
Shiboken::Object::invalidate(pyAct);
}
%CPPSELF.clear();
-for (PyObject *obj : lst) {
+for (auto *obj : lst) {
Shiboken::Object::invalidate(reinterpret_cast<SbkObject* >(obj));
Py_XDECREF(obj);
}