I have been trying to implement something that I believe should be pretty straightforward, but am having issues with it. In short, I have a class that has some Q_Properties, some of which I want to be namespace-level enum values. My issue is, if I move the enum and its namespace into a separate file, the QProperty system doesn't recognize the property is an enum value.
Here is a stripped down version to illustrate:
One file contains a namespace with an enum and the class I'm trying to use with the enums:
#ifndef ENUMPROPERTYTEST_H
#define ENUMPROPERTYTEST_H
#include <QObject>
#include "enumTest.h" //contains the other namespace and enum I want to use
namespace Test_SameFile {
Q_NAMESPACE
enum NSEnum_SameFile {
A1,
A2,
A3
};
Q_ENUM_NS(NSEnum_SameFile)
}
class EnumPropertyTest : public QObject
{
Q_OBJECT
Q_PROPERTY(int INT1 MEMBER myInt)
//this enum is declared in the same file and works as expected
Q_PROPERTY(Test_SameFile::NSEnum_SameFile ENUMVAL1 MEMBER a)
//this enum is declared in a separate header file and does not
Q_PROPERTY(Test_DiffFile::NSEnum_DiffFile ENUMVAL2 MEMBER g)
public:
explicit EnumPropertyTest() : QObject() {}
~EnumPropertyTest() {}
private:
int myInt = 5;
Test_SameFile::NSEnum_SameFile a = Test_SameFile::A2;
Test_DiffFile::NSEnum_DiffFile g = Test_DiffFile::T2;
};
#endif // ENUMPROPERTYTEST_H
My header file that contains another namespace and enum:
#ifndef ENUMTEST_H
#define ENUMTEST_H
#include <QObject>
namespace Test_DiffFile {
Q_NAMESPACE
enum NSEnum_DiffFile {
T1,
T2,
T3
};
Q_ENUM_NS(NSEnum_DiffFile)
}
#endif // ENUMTEST_H
My main:
#include <QObject>
#include <QMetaProperty>
#include <QDebug>
#include "enumpropertytest.h"
int main()
{
auto id1 = qRegisterMetaType<Test_SameFile::NSEnum_SameFile>();
auto id2 = qRegisterMetaType<Test_DiffFile::NSEnum_DiffFile>();
auto e1 = QMetaEnum::fromType<Test_SameFile::NSEnum_SameFile>();
qDebug() << "e1 id: " << id1 << ", valid:" << e1.isValid() << ", scope : " << e1.scope();
auto e2 = QMetaEnum::fromType<Test_DiffFile::NSEnum_DiffFile>();
qDebug() << "e2 id: " << id2 << ", valid:" << e2.isValid() << ", scope : " << e2.scope();
EnumPropertyTest t;
auto mo = t.metaObject();
for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i){
QString propName = mo->property(i).name();
auto prop = mo->property(i);
qDebug() << "Property: " << propName << "is an enum: " << prop.isEnumType();
}
return 0;
}
When I run this program, it outputs the following:
e1 id: 1024 , valid: true , scope : Test_SameFile
e2 id: 1025 , valid: true , scope : Test_DiffFile
Property: "INT1" is an enum: false
Property: "ENUMVAL1" is an enum: true
Property: "ENUMVAL2" is an enum: false
As you can see, the enum declared in the same file as the class is working as expected with the property system, but the one declared in the header file is not recognized to be an enum. How can I resolve this? I have deleted build folders, re-run qmake, everything obvious I could think of and no change.
I believe that in order for your
enumto be recognized byQt's meta type system, it needs to declared within either aQ_OBJECTor aQ_GADGET. If you don't want to make it part of your class (for understandable reasons like reusability, etc), you can declare a separate struct with theQ_GADGETmacro in it and then you can define yourenumthere. The bottom line is that if you want your type to be recognizable byQt's meta type system, but don't wanna make it aQObject, you can do so by just making it aQ_GADGET. The difference betweenQ_OBJECTandQ_GADGETis that a gadget cannot have signals and slots.So, it will look like this:
You can try it and see if it works.