I have a code, which works with Qt 5.5 and doesn't with Qt 5.2. Problem is with this enum:
#include <QtCore/QMetaType>
enum Area
{
Area_A,
Area_B,
Area_C
};
Q_DECLARE_METATYPE(Area)
Then I have an object, which exposes this area property:
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(Area area READ area WRITE setArea NOTIFY areaChanged)
public:
explicit MyClass(QObject *parent = 0)
: QObject(parent), m_area(Area_A){}
Area area() const { return m_area; }
void setArea(Area area) {
m_area = area;
emit areaChanged(area);
}
signals:
void areaChanged(Area area);
private:
Area m_area;
};
And main.cpp:
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>
#include <QtQml/QtQml>
#include "MyClass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<MyClass>("GLib", 1, 0, "MyClass");
MyClass controller;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("controller", &controller);
engine.load("./main.qml");
controller.setArea(Area_B);
return app.exec();
}
It compiles, everything is OK. But when I tried to use area property in qml:
import QtQuick 2.0
import QtQuick.Window 2.0
import GLib 1.0
Window {
visible: true
id: root
property int area: controller.area
Text {
id: name
text: "Test"
x: area * 30
y: area * 30
}
}
I have run-time errors, if Qt 5.2 is used (Linux, x64):
QMetaProperty::read: Unable to handle unregistered datatype 'Area' for property 'MyClass::area' file:///home/yech844/devel/test_qml/main.qml:10:24: Unable to assign [undefined] to int QMetaProperty::read: Unable to handle unregistered datatype 'Area' for property 'MyClass::area' file:///home/yech844/devel/test_qml/main.qml:10:24: Unable to assign [undefined] to int
Is it a bug in Qt? Why I can't use Enum, which is declared out of Class scope?
I don't know why the code works in Qt 5.5, but I know why it doesn't in Qt 5.2.
Q_DECLARE_METATYPE(...)
only makes the type available in static (compiled) context. For example, if you want to use the type in QVariant::fromValue(...)
. Here, the type you pass to the function can be processed during compile time, and for this, Q_DECLARE_METATYPE
is enough.
However, if you want to use a type in a pure runtime context, for example in a QML document, the Qt runtime doesn't know the type declared with Q_DECLARE_METATYPE
. For this, a function call (evaluated during runtime) needs to be made, and qRegisterMetatype
is the tool for this:
qRegisterMetaType<Area>("Area");
My guess for Qt 5.5 not needing that line is that qmlRegisterType
might detect the use of the meta type in the property and automatically calls the above function for you.