Exposing an enum in a QML signal

reprazent74

I have problems receiving the signal mySignal with the correct enum type in qml. I think I have done everything right:

  • The enum is in a separate class, derived from QObject
  • The enum is registered with Q_ENUMS
  • The class containing enum is registered with qmlRegisterUncreatableType
  • The class the signal is defined in, is also a QObject and also registered with qmlRegisterUncreatableType

Notable facts:

  • Running the program prints the log in the slot called from main.qml, but the signal emitted is not received in qml.
  • Uncommenting the emit in textclass.cpp allows the signal to be received in QML, but the comparison with the enum value is not triggered as it should be.

Why do I not recieve the signal with the enum up in QML and why cannot I compare to the enum value in QML even though is is exposed with Q_ENUMS?

I have seen a defect report regarding enums on the Qt defect page, so I understand that the support for enums in Qt is not rock solid. However, I really would like to be able to compare values to enums up in QML for signals received and at the moment I am not. For some reason the value entered into mySlot gladly accepts the same enum value that is not recognized in the signal handler. Code listings below.

Qt 5.4 on Ubuntu was used.

error.h:

#ifndef ERROR_H
#define ERROR_H

#include <QObject>
#include <QtQml>

class Error : public QObject
{
    Q_OBJECT
    Q_ENUMS(Type)

public:
    explicit Error(QObject *parent = 0) {Q_UNUSED(parent)};
    ~Error() {};

    static void RegisterTypes(void)
    {
        qmlRegisterUncreatableType<Error>("Types", 1, 0, "Error", "Error class uncreatable");
    }

    enum Type {
        OK = 0,
        FILE_ERROR
    };
};

#endif // ERROR_H

testclass.h:

#ifndef TESTCLASS_H
#define TESTCLASS_H

#include <QObject>
#include <QVariant>
#include <QDebug>

#include "error.h"

class TestClass : public QObject
{
    Q_OBJECT

public:
    explicit TestClass(QObject *parent = 0);
    ~TestClass();

    static void RegisterTypes(void)
    {
        qmlRegisterUncreatableType<TestClass>("TestClass", 1, 0, "TestClass", "TestClass uncreatable");
    };

signals:
    void mySignal(Error::Type arg);
    void mySignal(int arg);

public slots:
    void mySlot(QVariant arg);
};

#endif // TESTCLASS_H

testclass.cpp:

#include "testclass.h"

TestClass::TestClass(QObject *parent) : QObject(parent)
{

}

TestClass::~TestClass()
{

}

void TestClass::mySlot(QVariant arg)
{
    qDebug() << "mySlot called" << arg.toInt();
    int retval = static_cast<int>(arg.toInt());
    emit mySignal(static_cast<Error::Type>(retval));
    //   emit mySignal(retval);
}

main.cpp:

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

#include "error.h"
#include "testclass.h"

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

    Error::RegisterTypes();
    TestClass::RegisterTypes();

    TestClass* tPtr = new TestClass();

    engine.rootContext()->setContextProperty("_t", tPtr);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    return app.exec();
}

main.qml:

import QtQuick 2.4
import QtQuick.Window 2.2
import Types 1.0
import TestClass 1.0

Window {
    visible: true
    width: button.width + 20
    height: button.height + 20
    Rectangle {
        id: button
        width: theText.width + 20
        height: theText.height + 20
        anchors.margins: 10
        anchors.centerIn: parent
        border.width: 3

        Connections {
            target: _t

            onMySignal: {
                console.log("onMySignal: ", arg)
                if (arg == Error.OK) {
                    console.log("OK")
                }
                else if (arg == Error.FILE_ERROR) {
                    console.log("FILE_ERROR")
                }
                else {
                    console.log("UNDEFINED")
                }
            }
        }

        Text {
            id: theText
            anchors.centerIn: parent
            text: "press me!"
            font.pixelSize: 30
        }

        MouseArea {
            anchors.fill: parent
            onClicked: _t.mySlot(Error.FILE_ERROR)
            onPressed: button.scale = 0.9
            onReleased: button.scale = 1.0
        }
    }
}
reprazent74

The problems to this was two-fold.

First problem:

  • Error::Type was not registered within the Meta type system, the following line needs to be added after the Error class declaration:

    Q_DECLARE_METATYPE(Error::Type)

Second problem:

  • Was that I had selected the name 'Error' for the Error class when I registered it. This clashed with a built in type. The registration needs to be changed to this:

    qmlRegisterUncreatableType("Types", 1, 0, "ErrorClass", "Error class uncreatable");

    (The QML code would also need to be updated to reflect this of course.)

Changing these two things solved the problem, and the signal can now correctly be received in QML-code.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to access C++ enum from QML?

From Dev

C++ using signal slots for QML

From Dev

Is it possible to disconnect all slots from a signal in Qt5 QML?

From Dev

PyQt5 QML Signal to Python Slot?

From Dev

QML: one signal, multiple slots, possible?

From Dev

exposing enum native type to java through jni?

From Dev

How to use a custom Qt type with a QML signal?

From Dev

QML On Item Changed Signal

From Dev

emit qml signal on start application

From Dev

How to set property type of qml signal?

From Dev

Exposing complex C++ Qt object to QML

From Dev

Correct way to manage memory in Qt when exposing QObject class into qml?

From Dev

QML signal QT slot with QQuickView

From Dev

QML error on exposing child properties

From Dev

How to bind to a signal from a delegate component within a ListView in QML

From Dev

Qt enum in signal requires qRegisterMetaType

From Dev

How to pass enum class to QML?

From Dev

QAbstractListModel dataChanged signal not updating ListView (QML)

From Dev

exposing enum native type to java through jni?

From Dev

How to access C++ enum from QML?

From Dev

QML: Overriding a signal handler from other element

From Dev

emit qml signal on start application

From Dev

How to set property type of qml signal?

From Dev

QML - connect a signal from c++ to qml

From Dev

Exposing c++ model in qml

From Dev

Nested QML element onCompleted's signal not blocking the instanciation of QML objects

From Dev

How to pass enum class to QML?

From Dev

Signal between QML with Repeater

From Dev

Fail To Connect Qml signal to C++ Slot