PDA

View Full Version : "Enum class"/Q_ENUM use in QML? Cannot read property of undefined



sedi
21st March 2016, 12:02
Hi, I use a number of enums in my project, which I keep in a single "Enums" class, each of them defined by the c+11 way of "enum class" and the new Q_ENUM macro (instead of Q_ENUMS, as proposed here (https://woboq.com/blog/q_enum.html)).

I don't get them to work in QML, though - and all I can find about this topic (there are actually plenty of solutions!) is using the older concepts.

Below you find a minimized example project. On click, qml shall send Enums.DayOfWeek.MONDAY to a slot.
The result is:
qrc:/main.qml:17: TypeError: Cannot read property 'MONDAY' of undefined
where I'd expext qDebug output from the slot (environment: Qt 5.5, QtCreator 3.6, Win7x64).

Any ideas about how I could do it better / make it work?

Several Enums in enums.h

#ifndef ENUMS_H
#define ENUMS_H
#include <QObject>

class Enums
{
Q_GADGET

public:
enum class DayOfWeek {
SUNDAY=0,
MONDAY=1,
TUESDAY=2,
WEDNESDAY=3,
THURSDAY=4,
FRIDAY=5,
SATURDAY=6,
UNDEFINED=-1
};
Q_ENUM(DayOfWeek)

enum class NameOrder {
FIRST_FAMILY=0,
FAMILY_FIRST=1
};
Q_ENUM(NameOrder)

};

#endif // ENUMS_H


An object with a slot that takes such an enum: someobject.h


#ifndef SOMEOBJECT_H
#define SOMEOBJECT_H
#include <QObject>
#include <QDebug>
#include "enums.h"

class SomeObject : public QObject
{
Q_OBJECT
public:
explicit SomeObject(QObject *parent = 0): QObject(parent) {}
public slots:
void outputDay(Enums::DayOfWeek day) { qDebug()<<day; }
};

#endif // SOMEOBJECT_H


This is being registered in main.cpp


#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QtQml>
#include "enums.h"
#include "someobject.h"

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterUncreatableType<Enums>("url.Enums", 1, 0, "Enums", "You cannot create an instance of the Enums.");
qmlRegisterType<SomeObject>("url.SomeObject",1,0,"SomeObject");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}


And I try to use it in main.qml

import QtQuick 2.5
import QtQuick.Window 2.2
import url.SomeObject 1.0
import url.Enums 1.0


Window {
visible: true

SomeObject {
id: myObject
}

MouseArea {
anchors.fill: parent
onClicked: {
myObject.outputDay(Enums.DayOfWeek.MONDAY)
}
}
}

anda_skoa
21st March 2016, 12:32
Shouldn't that be



Enums.MONDAY

in the QML code?

Cheers,
_

sedi
21st March 2016, 12:37
Thank you for answering!
No, the result is
qrc:/main.qml:17: Error: Unknown method parameter type: Enums::DayOfWeek

Actually, the separation of all the Enums into different classes (e.g. having to specify them with "DayOfWeek") seems quite useful for me. From anywhere in the cpp code I access the enums like this:
Enums::DayOfWeek::MONDAY

I can't register the single Enums explicitly (qmlRegisterUncreatableType<Enums::DayOfWeek>()), because enum class is not a QObject. The problem has also been brought up - but not solved - here. (http://lists.qt-project.org/pipermail/interest/2015-April/016342.html)

anda_skoa
21st March 2016, 13:24
No, the result is

Hmm, ok, probably need an int there.



Actually, the separation of all the Enums into different classes (e.g. having to specify them with "DayOfWeek") seems quite useful for me. From anywhere in the cpp code I access the enums like this:
Enums::DayOfWeek::MONDAY

Looks like C++ syntax to me, never seen :: as a qualifier separator in JavaScript.

Cheers,
_

sedi
21st March 2016, 13:45
As for the :: syntax: yes, this is what I do from C++
"From anywhere in the cpp code I acc.."
I'd thought there should be a syntax like:
Enums.DayOfWeek.MONDAY in QML.

It seems a bit unsatisfying to either use deprecated stuff or not use the enums in QML at all. I will probably file a bug about this.

For now I will probably work with int interfaces. Thank you for your time and effort anda_skoa! Cheers!!

anda_skoa
21st March 2016, 15:19
As for the :: syntax: yes, this is what I do from C++
I'd thought there should be a syntax like: in QML.

JavaScript doesn't have enums, QML allows you to do something like enums by registering names.
What you are writing there is an Object or singleton called Enums with a subobject/property DayOfWeek with an enum.
But that doesn't exist on the C++ side either.



It seems a bit unsatisfying to either use deprecated stuff or not use the enums in QML at all

Or you use normal enums instead of enum classes and have comparable support on both language sides.
Would be my choice.

Cheers,
_

oiaavb
12th July 2016, 12:55
I've had a similar issue. Does it work if you add



qRegisterMetaType<Enums::DayOfWeek >("Enums::DayOfWeek")


and change the call to:



myObject.outputDay(Enums.MONDAY)

?

The one thing that is not so nice about this is that the parameter in the call doesn't refer to DayOfWeek anymore.

Regards

sedi
1st August 2016, 20:50
Yes, absolutely! The loss of the strong typisation is a pity - but at least I can use it :-) Thanks!