For instance I have enum from thirdparty library:
namespace Lib {
enum class Foo {
Bar,
Baz
};
};
I have tried use next wrapper
namespace Qml {
Q_NAMESPACE
using Foo = Lib::Foo;
Q_ENUMS(Foo)
}
with qmlRegisterUncreatableMetaObject
, but its don't work for me.
Can I register one in Meta Object System
for using in QML
, but without duplicates like:
class QmlObject {
Q_GADGET
public:
enum Foo {
Bar = Lib::Bar,
Baz = Lib::Baz
};
Q_ENUM(Foo)
};
Version of Qt
is 5.15.2
. Thanks.
I have found solution using the library magic_enum (at least v0.8.1, see limitations) and bit of modification in implementation of qmlRegisterType:
#include <QtQml/qqmlprivate.h>
#include <QtCore/private/qmetaobjectbuilder_p.h>
#include <magic_enum.hpp>
template<class T, class ... En>
int qmlRegisterTypeWithEnums(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
QML_GETTYPENAMES
//! register our enums here
QMetaObjectBuilder builder(&T::staticMetaObject);
([](QMetaObjectBuilder & builder)
{
QMetaEnumBuilder enumBuilder {
builder.addEnumerator(QByteArray::fromStdString(std::string{magic_enum::enum_type_name<En>()}))
};
enumBuilder.setIsScoped(magic_enum::is_scoped_enum_v<En>);
constexpr auto entries = magic_enum::enum_entries<En>();
for (const auto & pair : entries) {
enumBuilder.addKey(QByteArray::fromStdString(std::string{pair.second}), static_cast<int>(pair.first));
}
}(builder), ...);
//! ***************************
QQmlPrivate::RegisterType type = {
0,
qRegisterNormalizedMetaType<T *>(pointerName.constData()),
qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
uri, versionMajor, versionMinor, qmlName, builder.toMetaObject(),
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
QQmlPrivate::StaticCastSelector<T,QQmlParserStatus>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueSource>::cast(),
QQmlPrivate::StaticCastSelector<T,QQmlPropertyValueInterceptor>::cast(),
nullptr, nullptr,
nullptr,
0
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
Now for thirdparty enum
namespace Lib {
enum class Foo {
Bar = 2,
Baz = 4
};
};
and target Qt class
namespace SomeQml {
class QmlItem : public QObject
{
Q_OBJECT
using Foo = Lib::Foo; // its important use without namespace in declaration
Q_PROPERTY(Foo prop MEMBER m_val NOTIFY propChanged)
...
Q_INVOKABLE handleFoo(Foo v);
...
};
}
just call and use on QML side as QmlItem.Bar
or QmlItem.Baz
as an integer :
qmlRegisterTypeWithEnums<QmlItem, Lib::Foo>("my.pack", 1, 0, "QmlItem");