qmlRegisterType fails when Name does not match type
-
Hello,
I am not sure if this is a bug or a feature. Considering the following code:
main.cpp:#include <QObject> #include <QQmlContext> #include <QQmlListProperty> #include <QGuiApplication> #include <QQmlApplicationEngine> #include "testclasses.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // access to new type qmlRegisterType<TestObj>("TestClasses", 1, 0, "TestObj"); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // access to object TestCon testcon; engine.rootContext()->setContextProperty("testcon", &testcon); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
testclasses.h:
#ifndef TESTCLASSES_H #define TESTCLASSES_H #include <QObject> #include <QQmlListProperty> class TestObj: public QObject { Q_OBJECT public: TestObj(){} }; class TestCon: public QObject { Q_OBJECT Q_PROPERTY(QQmlListProperty<TestObj> oLists READ oLists) public: TestCon(){ m_olist.append(new TestObj()); m_olist.append(new TestObj()); m_olist.append(new TestObj()); } QQmlListProperty<TestObj> oLists() { return QQmlListProperty<TestObj>(this, m_olist); } private: QList<TestObj*> m_olist; }; #endif // TESTCLASSES_H
main.qml:
import QtQuick 2.9 import QtQuick.Window 2.2 import TestClasses 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Test Export List") Component.onCompleted:{ console.log(testcon.oLists) console.log(testcon.oLists[0]) console.log("Startup Complete") //testcon.oLists.append(new TestObj()) } }
If TestObj is not named "TestObj" in the registration call then it fails to register. Worse is if it appears to register it can cause the object to appear as a QVariant(QQmlListProperty<TestObj>) in QML. I ran into this in a large codebase and tried to reproduce. Changing the name to match the object name did fix the issue for the big codebase.
This works:
qmlRegisterType<TestObj>("TestClasses", 1, 0, "TestObj");
This fails:
qmlRegisterType<TestObj>("TestClasses", 1, 0, "crapobject");
I am not sure this is desired behavior or not. Is this supposed to fail?
System:
Windows 10 Pro 64 bit x86 (Intel)
Qt 5.9.7
mingw 5.3.0 compilerEdit:
I believe this person had the same issue:
qml-and-qvariant-qobjectlist -
Ooh, I got my test program to produce the QVariant wrapped version:
qmlRegisterType<TestCon>("TestClasses", 1, 0, "TestCon"); qmlRegisterType<TestObj>("TestClasses", 1, 0, "tObj");
This produces the object:
QVariant(QQmlListProperty<TestObj>)
That is the weird one where is "sort of" works.
-
Not very clear what is not working for you. Simply registering the TestObj with tObj should work.
qmlRegisterType<TestObj>("TestClasses", 1, 0, "tObj");
Do you mean to say that it is working only if you do the following ?
qmlRegisterType<TestCon>("TestClasses", 1, 0, "TestCon");
-
@dheerendra
Correct. If the object name TestObj does not match the name text (last parameter) the behavior is that it will either fail, or if another object is already registered with "TestClasses", produce the desired object wrapped in a QVariant. I think this may be something newer versions of Qt have introduced. The code I am working with worked fine on older versions of Qt. We are now on the LTS versions 5.9.Edit:
Note, it fails when accessing the list object being exported to QML. So it fails here in the QML:console.log(testcon.oLists) console.log(testcon.oLists[0])
-
I have tried with Qt 5.11.x and 5.9.x. It is working without any issue. Do you have complete sample to check your issue ?
-
I filed a bug report here. You can get the zip file with the entire project in there. It provides #defines to enable each CASE one at a time to illustrate the problem:
https://bugreports.qt.io/browse/QTBUG-71827Edit:
I had to reupload the project again to the bug report. The qml file had the check function commented out. It did not easily show the problem. Also, I just tested on Qt 5.11.2 and it complains about the object name not being uppercase but still produces the QVariant wrapped object in CASE 2. -
I added one more test case:
#ifdef CASE4 qmlRegisterType<TestCon>("TestClasses", 1, 0, "TestCon"); qmlRegisterType<TestObj>("TestClasses", 1, 0, "Badobject"); #endif
This works correctly. It is not the name matching that matters, but that the name must be uppercase on the first letter. Strange requirement.
-
Yes, QML components have to start with Capital Letter. That is the requirement.
-
Hello,
I am not sure if this is a bug or a feature. Considering the following code:
main.cpp:#include <QObject> #include <QQmlContext> #include <QQmlListProperty> #include <QGuiApplication> #include <QQmlApplicationEngine> #include "testclasses.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // access to new type qmlRegisterType<TestObj>("TestClasses", 1, 0, "TestObj"); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // access to object TestCon testcon; engine.rootContext()->setContextProperty("testcon", &testcon); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
testclasses.h:
#ifndef TESTCLASSES_H #define TESTCLASSES_H #include <QObject> #include <QQmlListProperty> class TestObj: public QObject { Q_OBJECT public: TestObj(){} }; class TestCon: public QObject { Q_OBJECT Q_PROPERTY(QQmlListProperty<TestObj> oLists READ oLists) public: TestCon(){ m_olist.append(new TestObj()); m_olist.append(new TestObj()); m_olist.append(new TestObj()); } QQmlListProperty<TestObj> oLists() { return QQmlListProperty<TestObj>(this, m_olist); } private: QList<TestObj*> m_olist; }; #endif // TESTCLASSES_H
main.qml:
import QtQuick 2.9 import QtQuick.Window 2.2 import TestClasses 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Test Export List") Component.onCompleted:{ console.log(testcon.oLists) console.log(testcon.oLists[0]) console.log("Startup Complete") //testcon.oLists.append(new TestObj()) } }
If TestObj is not named "TestObj" in the registration call then it fails to register. Worse is if it appears to register it can cause the object to appear as a QVariant(QQmlListProperty<TestObj>) in QML. I ran into this in a large codebase and tried to reproduce. Changing the name to match the object name did fix the issue for the big codebase.
This works:
qmlRegisterType<TestObj>("TestClasses", 1, 0, "TestObj");
This fails:
qmlRegisterType<TestObj>("TestClasses", 1, 0, "crapobject");
I am not sure this is desired behavior or not. Is this supposed to fail?
System:
Windows 10 Pro 64 bit x86 (Intel)
Qt 5.9.7
mingw 5.3.0 compilerEdit:
I believe this person had the same issue:
qml-and-qvariant-qobjectlist@fcarney said in qmlRegisterType fails when Name does not match type:
This fails:
qmlRegisterType<TestObj>("TestClasses", 1, 0, "crapobject");QML type names always must begin with a capital letter.
Is this your issue? -
Yes, the issue is the requirement of the upper case letter at the beginning.
The original issue is that it had worked in an older version of Qt and then when upgrading to 5.9.7 it started displaying this behavior. It was not obvious what the problem was. I did observe that in 5.11.2 it now complains and says it needs a capital letter at the beginning so at least there is a way to track it down in later versions.
Thanks for everyone's help!