yudjin yudjin - 14 days ago 6
C++ Question

Enum in Qt property

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?

Answer

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.

Comments