1
votes

I have an enum defined in a QObject with a few values, and I am registering the enum as QFlags as the Qt documentation specifies. I have registered the enum and the QObject as metatypes that I can access just fine from QML.

The problem is that once I have a C++ QObject slot defined that has the QFlags as an argument it doesn't get an error when it is called, but instead passes in the first defined value in the enum (ie. its value is that of the enum entry with the number 0).

It is hard to describe, so I created a small working example (using C++11/Qt 5.7). When you run it and click anywhere in the window that opens, QFlags<QMLThing::MyEnum>(VALA) is printed out, even though in main.qml I am calling thing.doThing(QMLThing.VALC).

I started by creating a "Qt Quick Application" in QtCreator. Then added a class called "QMLThing". Here is the source code for each file:

QMLThing.hpp

#ifndef QMLTHING_HPP
#define QMLTHING_HPP

#include <QObject>

class QMLThing : public QObject
{
    Q_OBJECT

public:
    enum MyEnum {
        VALA = 0,
        VALB = 1,
        VALC = 2,
        VALD = 4,
    };

    Q_ENUM(MyEnum)
    Q_DECLARE_FLAGS(MyEnums, MyEnum)

public:
    explicit QMLThing(QObject *parent = 0);

public slots:
    void doThing(QMLThing::MyEnums val);
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QMLThing::MyEnums)
Q_DECLARE_METATYPE(QMLThing::MyEnums)

#endif // QMLTHING_HPP

QMLThing.cpp

#include "QMLThing.hpp"

#include <QDebug>

QMLThing::QMLThing(QObject *parent) : QObject(parent)
{}

void QMLThing::doThing(QMLThing::MyEnums val)
{
    qDebug() << val;
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>

#include "QMLThing.hpp"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<QMLThing>("stuff", 1, 0, "QMLThing");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2

import stuff 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MouseArea {
        anchors.fill: parent
        onClicked: {
            thing.doThing(QMLThing.VALC)
        }
    }

    Text {
        text: qsTr("Click here and look in the terminal")
        anchors.centerIn: parent
    }

    QMLThing {
        id: thing
    }
}

This seems a lot like a bug, but maybe I'm just missing something.

2

2 Answers

1
votes

You're missing Q_FLAG(MyEnums):

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>

#include <QObject>

class QMLThing : public QObject
{
    Q_OBJECT

public:
    enum MyEnum {
        VALA = 0,
        VALB = 1,
        VALC = 2,
        VALD = 4,
        VALE = VALC | VALD
    };

    Q_DECLARE_FLAGS(MyEnums, MyEnum)
    Q_FLAG(MyEnums)

public:
    explicit QMLThing(QObject *parent = 0) :
        QObject(parent)
    {
    }

public slots:
    void doThing(QMLThing::MyEnums val)
    {
        qDebug() << val;
    }
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QMLThing::MyEnums)
Q_DECLARE_METATYPE(QMLThing::MyEnums)

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<QMLThing>("stuff", 1, 0, "QMLThing");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

#include "main.moc"

main.qml:

import QtQuick 2.7
import QtQuick.Window 2.2

import stuff 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MouseArea {
        anchors.fill: parent
        onClicked: {
            thing.doThing(QMLThing.VALC)
            thing.doThing(QMLThing.VALC | QMLThing.VALD)
        }
    }

    Text {
        text: qsTr("Click here and look in the terminal")
        anchors.centerIn: parent
    }

    QMLThing {
        id: thing
    }
}

As mentioned here, you don't need to use Q_ENUM():

Note: The Q_FLAG macro takes care of registering individual flag values with the meta-object system, so it is unnecessary to use Q_ENUM() in addition to this macro.

0
votes

Not sure exactly what is going on but first of all:

public:
enum MyEnum {
    VALA,
    VALB,
    VALC,
    VALD,
};

You need to remove the last coma. I would also recommend to set at least the first enum, to a certain value, usually 0 so you know where you are going but no need to set the following enum items as they will be auto-incremented from the last one set.

Last, I'm not entirely sure about the QMLThing.ValC, shouldn't it be QMLThing::MyEnums::ValC ?