reprazent74
reprazent74

Reputation: 95

Exposing an enum in a QML signal

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

Notable facts:

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
        }
    }
}

Upvotes: 2

Views: 4240

Answers (1)

reprazent74
reprazent74

Reputation: 95

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.

Upvotes: 2

Related Questions