Dynamic cast (interface) class in QML
-
Hello all,
what is the best practice to make an C++ interface/base class accessible in QML?
For example (not complete and not right):
class IFoo : public QObject { explicit IFoo(QObject *parent = nullptr) {} ~virtual IFoo() {} virtual void overrideMe() = 0; } class FooA : public IFoo { FooA(QObject *parent = nullptr) {} } class FooB : public IFoo { FooB(QObject *parent = nullptr) {} }
main:
int main(int argc, char *argv[]) { QQmlApplicationEngine engine; IFoo *foo1 = new FooA; IFoo *foo2 = new FooB; FooB *foo3 = new FooB; engine.rootContext()->setContextProperty("foo", foo1); // which type it is in QML? IFoo? // or engine.rootContext()->setContextProperty("foo", qobject_cast<FooA*>(foo1)); // and engine.rootContext()->setContextProperty("foo2", qobject_cast<FooB*>(foo2)); engine.rootContext()->setContextProperty("foo3", foo3); // FooB }
Is there a way to cast foo1 in QML? Or is this fundamentally a bad idea and evidence of bad code?
Thank you very much!
-
You're right.
And how can i use and cast the Base in QML?
Or is this impossible and i have to use the exact type in QML?
What is the best way to represent this in QML then?What first came to my mind:
Item { property QtObject modul: foo1 ? foo1 : foo2 property bool isFoo1: foo1 ? true : false Component.onCompleted: { modul.overrideMe() } }
But this is of course quite bullshit and I have to check each time which type is present.
Are there any other ideas? -
I would guess you need to start with QML_INTERFACE and QML_IMPLEMENTS_INTERFACES
-
Hello folks,
I would like to give some feedback.
Basically, it's quite simple: Only the interface class is passed as a ContextProperty, QML then automatically casts the class into the correct type.
This also works very reliably.int main(int argc, char *argv[]) { QQmlApplicationEngine engine; IFoo *foo = new FooA; engine.rootContext()->setContextProperty("iFoo", foo); // in QML it is FooA }
For differentiation, I return the class name in the interface class with the meta system. I have not found a function in QML that does this reliably (but I also use 5.9).