diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2025-06-26 12:23:38 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2025-06-30 22:24:27 +0200 |
| commit | bc6dc807c1946863c5a8481272566edf696ee7b6 (patch) | |
| tree | b6e336e85ccfe6eca83be2d191f1f0427d9c927d /sources/pyside6/libpyside/dynamicqmetaobject.cpp | |
| parent | 82895a377e301cbf2526490f9e32c9b261aa3f6e (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.cpp | 37 |
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); } } |
