Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't declare Q_ENUM from an enum defined in another class

Tags:

c++

qt

This documentation states

If you want to register an enum that is declared in another class, the enum must be fully qualified with the name of the class defining it. In addition, the class defining the enum has to inherit QObject as well as declare the enum using Q_ENUMS().

However I can't make this work, in the following example.

Class A:

#ifndef CLASSA_H
#define CLASSA_H

#include <classb.h>

class ClassA : public QObject
{
   Q_OBJECT
   Q_ENUMS(ClassB::TestEnum)

public:
   explicit ClassA(QObject *parent = 0) : QObject(parent)
   {
      const QMetaObject *metaObj = this->metaObject();
      qDebug() << metaObj->enumeratorCount();
   }
};

#endif // CLASSA_H

ClassB:

#ifndef CLASSB_H
#define CLASSB_H

#include <QDebug>
#include <QMetaEnum>
#include <QObject>

class ClassB : public QObject
{
   Q_OBJECT
   Q_ENUMS(TestEnum)

public:
   enum TestEnum { A, B, C };

   explicit ClassB(QObject *parent = 0) : QObject(parent)
   {
      const QMetaObject *metaObj = this->metaObject();
      qDebug() << metaObj->enumeratorCount();
   }
};

#endif // CLASSB_H

main:

#include <classa.h>
#include <classb.h>

int main() 
{
   ClassA objectA;
   ClassB objectB; 
}

Expected output:

1

1

Actual Output:

0

1

like image 309
onezeno Avatar asked Sep 11 '14 19:09

onezeno


1 Answers

Here is a summary of a little research:

  • Information stated in the documentation about registration of a enum declared in another class looks outdated.

  • Q_ENUMS(Class::EnumName doesn't create a new enumerator, and useless.

  • When you declare a new Q_PROPERTY in ClassA you should use full form of the enum ClassB::EnumName.

  • As soon as EnumName is registered in ClassB it doesn't need to be registered any more.

  • A property created using a enumerator from another class works correctly.

    class ClassA : public QObject
    {
    public:
     Q_OBJECT       
     Q_PROPERTY(ClassB::TestEnum test READ test)
    
    public:
    explicit ClassA(QObject *parent = 0)
    {
        const QMetaObject *metaObj = this->metaObject();
        qDebug() << metaObj->enumeratorCount();
    
        QMetaProperty property = metaObj->property(metaObj->indexOfProperty("test"));
        if (property.isEnumType())
        {
            const QMetaEnum& enumerator = property.enumerator();
    
            qDebug() << enumerator.name();
    
            for (int i = 0 ; i < enumerator.keyCount(); i++)
            {
                qDebug() << QLatin1String(enumerator.key(i)) <<  enumerator.value(i);           
            }
        }
    }
    ClassB::TestEnum test() const
    {
        return ClassB::A;
    }
    };
    

Output:

0 
TestEnum 
"A" 0 
"B" 1 
"C" 2 
like image 78
Ezee Avatar answered Oct 01 '22 09:10

Ezee