aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpyside/dynamicqmetaobject.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2025-06-26 12:23:38 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2025-06-30 22:24:27 +0200
commitbc6dc807c1946863c5a8481272566edf696ee7b6 (patch)
treeb6e336e85ccfe6eca83be2d191f1f0427d9c927d /sources/pyside6/libpyside/dynamicqmetaobject.cpp
parent82895a377e301cbf2526490f9e32c9b261aa3f6e (diff)
MetaObjectBuilder: Handle quint64 enumerations
In the delayed creation of QMetaEnum's in MetaObjectBuilder, when parsing QEnum-decorated values, check for large quint64 values and add them correctly. For class QMetaEnum, instead of exposing the newly added functions "std::optional<quint64> value64()" and similar, inject code handling large values into the existing bindings since Python's int type is able to represent the type. Adapt to qtbase/d41b87e06742b491c4e36aeae32e03f85b078d69. [ChangeLog][PySide6] @QEnum, @QFlag and QMetaEnum now support unsigned 64 bit values for QML usage (with the exception of Qt Widgets Designer). Task-number: QTBUG-27451 Task-number: QTBUG-111926 Task-number: PYSIDE-1735 Change-Id: Ib0b26dbc350c404d354c8f53afee946e29f2adb3 Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/pyside6/libpyside/dynamicqmetaobject.cpp')
-rw-r--r--sources/pyside6/libpyside/dynamicqmetaobject.cpp37
1 files changed, 29 insertions, 8 deletions
diff --git a/sources/pyside6/libpyside/dynamicqmetaobject.cpp b/sources/pyside6/libpyside/dynamicqmetaobject.cpp
index 54e814523..61327cc1b 100644
--- a/sources/pyside6/libpyside/dynamicqmetaobject.cpp
+++ b/sources/pyside6/libpyside/dynamicqmetaobject.cpp
@@ -24,12 +24,24 @@
#include <private/qmetaobjectbuilder_p.h>
#include <cstring>
+#include <limits>
#include <vector>
using namespace Qt::StringLiterals;
using namespace PySide;
+// QMetaEnum can handle quint64 or int values. Check for big long values and force
+// them to quint64 (long=64bit/int=32bit on Linux vs long=32bit on Windows).
+// Note: underflows are currently not handled well.
+static QVariant longToEnumValue(PyObject *value)
+{
+ int overflow{};
+ const long longValue = PyLong_AsLongAndOverflow(value, &overflow);
+ return overflow != 0 || longValue > std::numeric_limits<int>::max()
+ ? QVariant(PyLong_AsUnsignedLongLong(value)) : QVariant(int(longValue));
+}
+
// MetaObjectBuilder: Provides the QMetaObject's returned by
// QObject::metaObject() for PySide6 objects. There are several
// scenarios to consider:
@@ -395,9 +407,13 @@ QMetaEnumBuilder
auto enumbuilder = builder->addEnumerator(name);
enumbuilder.setIsFlag(flag);
enumbuilder.setIsScoped(scoped);
+ for (const auto &item : entries) {
+ if (item.second.typeId() == QMetaType::ULongLong)
+ enumbuilder.addKey(item.first, item.second.toULongLong());
+ else
+ enumbuilder.addKey(item.first, item.second.toInt());
+ }
- for (const auto &item : entries)
- enumbuilder.addKey(item.first, item.second);
m_dirty = true;
return enumbuilder;
}
@@ -678,21 +694,26 @@ void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type)
AutoDecRef items(PyMapping_Items(members));
Py_ssize_t nr_items = PySequence_Length(items);
- QList<std::pair<QByteArray, int> > entries;
+ MetaObjectBuilder::EnumValues entries;
+ entries.reserve(nr_items);
+ bool is64bit = false;
for (Py_ssize_t idx = 0; idx < nr_items; ++idx) {
AutoDecRef item(PySequence_GetItem(items, idx));
AutoDecRef key(PySequence_GetItem(item, 0));
AutoDecRef member(PySequence_GetItem(item, 1));
AutoDecRef value(PyObject_GetAttr(member, Shiboken::PyName::value()));
const auto *ckey = String::toCString(key);
- auto ivalue = PyLong_AsSsize_t(value);
- entries.push_back(std::make_pair(ckey, int(ivalue)));
+ QVariant valueV = longToEnumValue(value.object());
+ if (valueV.typeId() == QMetaType::ULongLong)
+ is64bit = true;
+ entries.append(std::make_pair(QByteArray(ckey), valueV));
}
auto enumBuilder = addEnumerator(name, isFlag, true, entries);
QByteArray qualifiedName = ensureBuilder()->className() + "::"_ba + name;
- auto metaType =
- PySide::QEnum::createGenericEnumMetaType(qualifiedName,
- reinterpret_cast<PyTypeObject *>(obEnumType));
+ auto *typeObject = reinterpret_cast<PyTypeObject *>(obEnumType);
+ auto metaType = is64bit
+ ? PySide::QEnum::createGenericEnum64MetaType(qualifiedName, typeObject)
+ : PySide::QEnum::createGenericEnumMetaType(qualifiedName, typeObject);
enumBuilder.setMetaType(metaType);
}
}