Q_DECLARE_METATYPE ... C struct straight to QML?
-
Hi,
I have been intrigued by the intent of the macro Q_DECLARE_METATYPE. I would like to use it to take some legacy code C structs and use them directly in QML. I can get as far as getting the variant to QML, but I can't extract the individual values of the struct. QML recognizes at least the name of the struct, but I can't figure out how to cast the QVariant back into the struct on the QML side. The only way seems to be to have a C++ proxy class that turns the structs into QVariantMaps, and then everything works just fine. I'm trying to find a much more lazy approach, given the size of the legacy code base in C.
Here is a small struct example. The comments in the code show what I'm thinking in terms of meeting the requirements for using Q_DECLARE_METATYPE, and where the code falls short.
C++ Main function and declaration of the struct:
@
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QString>
#include <QDebug>
#include <QQmlContext>
#include <QMetaType>
#include <QtQml>
#include <QObject>struct MyStruct
{
// Q_OBJECT - don't even think about it. MOC throws a fit.
int one;
QString two;
};
Q_DECLARE_METATYPE(MyStruct)int main(int argc, char *argv[])
{QGuiApplication app(argc, argv); int metaTypeId = 0; MyStruct* pEmpty = new MyStruct; // Cpp provides default constructor. qDebug()<< "Empty One: " << pEmpty->one; // Cpp CAN extract the elements of qDebug()<< "Empty Two: " << pEmpty->two; // the default constructor. delete (pEmpty); // default destructor is provided. // qDebug()<< "Deleted Two: " << pEmpty->two; // Causes exception as expected MyStruct s={1, "two"}; // Cpp provides a default copy constructor QVariant var; var.setValue(s); MyStruct t=var.value<MyStruct>(); // Cpp provides method make a struct from a QVariant qDebug()<< "C++ One: " << t.one; // Cpp CAN extract the elements of the struct after being a QVariant. qDebug()<< "C++ Two: " << t.two; // but must be recast to a struct. metaTypeId = qRegisterMetaType<MyStruct>("MyStruct"); qDebug() << "My registered ID: " << metaTypeId; // CAN register the struct as a metatype. // canNOT register the struct as a QML type (probably because it is not a Q_OBJECT) // qmlRegisterType<MyStruct>("TMyStruct", 1, 0, "TMyStruct"); QQmlApplicationEngine engine; QQmlContext* ctxt = engine.rootContext(); ctxt->setContextProperty("structObject", var); // CAN reference the instance of the variant of the struct in QML engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec();
}
@QML File
@
import QtQuick 2.3
import QtQuick.Window 2.2Window {
Component.onCompleted: {
console.log("A StructObject is:", structObject);
console.log("Has type: ", typeof(structObject));
console.log("Has string: ", structObject.toString());
console.log("Has int value: ", structObject.one);
console.log("Has string value: ", structObject.two);
console.log("Has length: ", structObject.length);
Qt.quit();
}
}
@Results:
@
QML debugging is enabled. Only use this in a safe environment.
Empty One: -1232878432
Empty Two: ""
C++ One: 1
C++ Two: "two"
My registered ID: 1027
OpenGL Warning: Failed to connect to host. Make sure 3D acceleration is enabled for this VM.
qml: A StructObject is: QVariant(MyStruct)
qml: Has type: object
qml: Has string: QVariant(MyStruct)
qml: Has int value: undefined
qml: Has string value: undefined
qml: Has length: undefined
@Thanks in advance for the help.
Brian