Hi,
Thanks for the hints - almost everything is now working (and you can
ignore my original issue about changed behaviour).
The remaining problem is that if I query the generated meta-object for
the QMetaEnum then its QMetaType is always invalid.
Looking at the QMetaObjectBuilder source I can't see where the QMetaType
passed to setMetaType() is actually used. As far as I can tell the enum
meta-types should be stored immediately after the property meta-types in
the QMetaObject data. However if you look at the relevant part of
qobjectmetaobjectbuilder.cpp (lines 1411 to 1441) you can see that no
enum meta-types are stored and a nullptr (for the QMetaObject's
meta-type) immediately follows the property meta-types. As my test case
only has one enum I think that it's seeing that nullptr as its
meta-type.
As QML defined enum properties are not allowed, would that mean that
this code wouldn't have been exercised?
Attached is a patch that fixes the problem for me - but with very little
testing.
Regards,
Phil
On 04/10/2024 15:31, Fabian Kosmale wrote:
Hi,
QMetaProperty::isEnumType's documentation probably should be adjusted
to mention that it really is about having an enum marked with Q_ENUM,
not about generic C++ enums.
For your use-case: I suspect you need to create a dynamic meta-type
for your enum (or rather, the QtPrivate::QMetaTypeInterface), and pass
that to `QMetaEnumBuilder::setMetaType`. You can probably get away by
copying most information from the QMetaTypeInterface of the underlying
type, and just adjusting name and setting the flags.
I suspect we don't have this kind of code in Qt, becuse QML currently
doesn't allow QML defined enum properites, which would be the place
where it's needed.
Kind regards,
Fabian Kosmale
On 04.10.24 14:43, Phil Thompson wrote:
Hi Fabian,
The change was https://codereview.qt-project.org/c/qt/qtbase/+/559265
Reverting this change means I get the same behaviour as I get with
v6.7.
I am (and always have been) using QMetaObjectBuilder and
addEnumerator() (the overload that takes a QByteArray argument).
I've compared the following scenarios...
a moc-generated meta-object where Q_ENUM is not used
a moc-generated meta-object where Q_ENUM is used
a dynamically created meta-object.
...for v6.7.1, v6.8.0 and v6.8.0 with the change reverted. In each
case I looked at the results of...
QMetaEnum.metaType().isValid()
QMetaProperty.metaType().isValid()
QMetaProperty.isEnumType()
The results in all cases for v6.7.1 and v6.8.0 with the change
reverted were identical.
For moc-generated meta-objects...
- the results were consistent across all versions of Qt
- QMetaProperty.metaType().isValid() always returned true (even if
QMetaEnum.metaType().isValid() returned false)
- QMetaProperty.isEnumType() returned true if Q_ENUM was used and
false if it wasn't
For dynamically created meta-objects...
- the results were dependent on the version of Qt
- QMetaProperty.metaType().isValid() always returned false
- QMetaProperty.isEnumType() returned true for v6.7.1 and false for
v6.8.0
I was surprised by the result of QMetaProperty.isEnumType() for a
moc-generated meta-object without Q_ENUM. The docs suggest this should
be true for all enums whether or not Q_ENUM is used.
This actually means that the v6.8 dynamic behaviour is closer to the
moc-generated behaviour but means it seems to be impossible to
dynamically create an enum property where QMetaProperty.isEnumType()
returns true.
Some questions...
Why does QMetaProperty.metaType().isValid() always return true for
moc-generated meta-objects and false for dynamically created
meta-objects?
Is there any way to dynamically register an enum with the meta-type
system (so that QMetaEnum.metaType().isValid() returns true)?
Regards,
Phil
On 04/10/2024 08:02, Fabian Kosmale via Development wrote:
Hi Phil,
I'm not quite sure which change caused the issue, and I believe a
bugreport with a reproducer might shed some light on the issue.
Nevertheless, if you're already using the private QMetaObjectBuilder
API, I would expect that it should work if you build the enum also
dynamically via addEnumerator and then working with the returned
QMetaEnumBuilder.
Kind regards,
Fabian
On 03.10.24 17:52, Phil Thompson via Development wrote:
On 03/10/2024 16:31, Volker Hilsheimer wrote:
On 3 Oct 2024, at 17:07, Phil Thompson via Development
<development@qt-project.org> wrote:
On 03/10/2024 15:44, Thiago Macieira wrote:
On Thursday 3 October 2024 05:06:08 GMT-7 Phil Thompson via
Development wrote:
Yes, that's the change - commenting out the new test fixes the
problem.
I am dynamically building the meta-object. You don't really
build an
enum, you just provide a description of it to the meta-object.
It would
be nice to be able to register an enum with the meta-type system
dynamically.
Or you can set the EnumOrFlag flag in the QMetaProperty flags
field to
force the
constructor to search.
Sorry, can you be more specific? I can't see how to do it given
the private nature of the flags.
Phil
Hey Phil,
How do you generate a dynamic meta object without using private
APIs?
Do you use QMetaObjectBuilder (which is private), or do you
generate
the tables and arrays by hand?
If you use QMetaObjectBuilder, then
QMetaPropertyBuilder::setEnumOrFlag would be the way to go.
Volker
I'm using QMetaObjectBuilder and already calling setEnumOrFlag, so
that doesn't seem to solve the problem.
An alternative that would work for me would be to bypass the new
test if the meta-type was invalid (ie. the enum wasn't registered)
but I don't know if that would nullify the purpose of the new test.
Phil
-- Fabian Kosmale
Manager R&D
The Qt Company GmbH
Erich-Thilo-Str. 10
D-12489 Berlin
fabian.kosm...@qt.io
+49 1638686070
--- qmetaobjectbuilder.cpp.orig 2024-10-05 18:13:54
+++ qmetaobjectbuilder.cpp 2024-10-05 18:11:53
@@ -1251,7 +1251,7 @@
// Output the methods in the class.
Q_ASSERT(!buf || dataIndex == pmeta->methodData);
// + 1 for metatype of this metaobject
- int parameterMetaTypesIndex = int(d->properties.size()) + 1;
+ int parameterMetaTypesIndex = int(d->properties.size() + d->enumerators.size()) + 1;
for (const auto &method : d->methods) {
[[maybe_unused]] int name = strings.enter(method.name());
int argc = method.parameterCount();
@@ -1417,6 +1417,11 @@
*types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
types++;
}
+ for (const auto &enumerator : d->enumerators) {
+ QMetaType mt = enumerator.metaType;
+ *types = reinterpret_cast<QtPrivate::QMetaTypeInterface *&>(mt);
+ types++;
+ }
// add metatype interface for this metaobject - must be null
// as we can't know our metatype
*types = nullptr;
--
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development