Reputation: 95
I have problems receiving the signal mySignal
with the correct enum type in qml. I think I have done everything right:
QObject
Q_ENUMS
qmlRegisterUncreatableType
QObject
and also registered with qmlRegisterUncreatableType
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
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