Solved Expose an enum from a non-QObject member variable to QML
-
Apologies if my terminology is loose, I'm at the edge of my understanding here.
I've got a C++ class (class A) from a library that I want to interface with QML. I wrote a QObject derived class (Class W) that has a private member A. W provides methods that QML can call and W calls the corresponding methods on A in turn.
However, I haven't been able to get public enums from class A defined in QML. I've tried a bunch of variations on this:
class A { public: enum class ENUM { ONE, TWO, THREE }; };
class W : public QObject { Q_OBJECT Q_ENUMS(M_ENUM) public: typedef A::ENUM M_ENUM; private: A m_A; };
It compiles, but the enum is still undefined in QML.
-
@Yosemite Have you registered the type (QObject derived class)?
-
Yeah, I remembered to do that, but good idea. Something is incorrect in the way I've tried to expose the member class enum through the wrapper. The typedef doesn't work, but re-writing the enum declaration in the wrapper does work.
Once I re-write the enum declaration entirely in W, I can access it in QML with
W.ONE
But when I just use the typedef and try to access it in QML it is undefined.
-
@Yosemite I would guess it's about how Q_ENUMS macro works. Open the moc_w.cpp (or moc_whatever-your-cpp-file-name-is) and you can see what's the result of that macro. Maybe it's just not meant to work with typedefs.
-
@Eeli-K finally in Qt 5.8 there's a way to use enums from QML.
see https://www.kdab.com/new-qt-5-8-meta-object-support-namespaces/?utm_source=dlvr.it&utm_medium=twitter
unfortunately this won't work with your enums inside a library -
If you are using Qt < 5.8, the following works:
class Type : public QObject{ Q_OBJECT Q_ENUMS(EnType) public: enum EnType{ ONE, TWO, THREE }; Q_ENUMS(EnType) };
After exposing the object to QML, you can use it in the following way:
var res; if(res === Type.ONE){ .... }
-
@Yosemite The more I think about this the more natural it feels this just can't work. Enums and typedefs are both compile-time instructions to the compiler, they will not result to runtime objects or anything like that. Q_ENUM is a macro which takes literal text and creates runtime things out of it. It just can't handle typedef or anything else than literal enum definition with actual names. With your typedef it creates nothing and the typedef works like in standard C++ without Qt-specific runtime behavior, so it can't be used in QML. Your only options seems to be to re-write the enum declaration entirely in W as you have already done. For safety I would use
ONE = (int)A::ENUM::ONE,
etc. to make it sure they have the same values so that if the A::ENUM is changed the values will correspond. If you haven't written A yourself, that is.
-
Thanks everybody, this has been very useful. I like your safety step Eeli, I'll adopt that.