Invoke slot of child of child of QQmlPropertyMap?
-
[This is a duplicate of StackOverflow question I asked, but I am hoping it find a different audience with other solutions.]
BTW, this is for a Qt 5.15 application.
I am working on a design where I have a class (call it
MyBaseClass
) that inherits from QQmlPropertyMap. It implements some additional behaviors for my system which are then used by other classes that inerit fromMyBaseClass
(e.g.ChildClass
).From QML, (QtQuick), I wish to invoke a slot (
mySlot()
) ofChildClass
. When I try, I get the following issues in the Application Output (mentioningMyBaseClass
) even though I am only usingChildClass
.qrc:/main.qml:17: TypeError: Property 'mySlot' of object MyBaseClass(0x55f88ef86b50) is not a function qrc:/main.qml:24: TypeError: Property 'mySlot' of object MyBaseClass(0x55f88ef86b50) is not a function
I also tried implementing sending signals from QML, but I get a similar issue trying to bind to the QML emitted signals. (I am not adding that example.)
My "gut" says that the problem is I am not doing things the "Qt Way," but I can't figure out what it is.
[I like to say "If you have to do a lot of work to make something work, you aren't doing it the 'Qt Way.'"]Does anyone know the Qt Way to do this? I almost at doing C++ Templates, but I'm not sure I can extend the functionality I want to add to MyBaseClass that way.
I'm also not totally surprised noting there are some interesting ways you have to initialize a member inheriting directly from QQmlPropertyMap.
Here is the minimum example code of the problem to demonstrate the problem. (I'm leaving out the .pro file since it is trivial to make.)
MyBaseClass.h
#include <QQmlPropertyMap> class MyBaseClass : public QQmlPropertyMap { Q_OBJECT public: explicit MyBaseClass(QObject *parent = nullptr) : QQmlPropertyMap(this, parent) {} };
ChildClass.h
#include "MyBaseClass.h" #include <QObject> #include <QDebug> class ChildClass : public MyBaseClass { Q_OBJECT public: ChildClass(QObject *parent = nullptr) : MyBaseClass(parent) {} public slots: void mySlot() { qDebug() << "This is mySlot"; }; };
main.qml
import QtQuick 2.15 import QtQuick.Window 2.15 Window { id: theMainWindow width: 640 height: 480 visible: true title: qsTr("Hello World") property QtObject cData: childData; onCDataChanged: { childData.mySlot(); } Timer { // wait a bit before calling repeat: false interval: 2000 running: true onTriggered: childData.mySlot(); } }
main.cpp
int main(int argc, char *argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QGuiApplication app(argc, argv); QQmlApplicationEngine engine; auto childData = new ChildClass(); engine.rootContext()->setContextProperties({ QQmlContext::PropertyPair{"childData", QVariant::fromValue(childData)}, }); const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
-
The answers at this time in the StackOverflow thread here are correct.
The instantiation of template constructor forQQmlPropertyMap
needs to know the derived type to register it. The template is being instantiated forMyBaseClass
, and therefore the metaobject system recognizes that as the most derived type ofChildClass
.Is the base class that inherits from
QQmlPropertyMap
, plus the derived class that inherits from the base necessary? Can the code be restructured to either directly inheritQQmlPropertyMap
inChildClass
, or compose and expose theMyBaseClass
instance as a property ofChildClass
? -