0

Q_ENUM does not work as (I) expected when used on enum that is inherited.

For example there is base struct A (legacy class) and B that inherits from A and from QObject. A has an enum and B has Q_ENUM of this enum.

b.h

#pragma once

#include <QObject>
#include <QDebug>

struct A
{
    A() = default;
    virtual ~A() = default;

    enum E_FOO{
        FOO = 1000,
        FOOO,
        FOOOO
    };
};

class B
        : public QObject
        , public A
{
    Q_OBJECT
    Q_ENUMS(E_FOO)  // OPTION 1 doesn't work

public:
    B() {
        qDebug() << "enums from A" << B::FOO << B::FOOO<<B::FOOOO;
        qDebug() << "enums from B" << B::BAR  << B::BARR  << B::BARRR;
    }
//    Q_ENUM(E_FOO)  // OPTION 2 doesn't work

//    using E_FOO_FORWARDED = A::E_FOO;  // OPTION 3 doesn't work
//    Q_ENUM(E_FOO_FORWARDED)


   // additional enum (for testing a "normal" case)
    enum E_BAR {
        BAR = 1111,
        BARR,
        BARRR
    };
    Q_ENUM(E_BAR)
};

here is some qml file to load that just prints values of enums when created.

MainWindow.qml

import QtQuick 2.7
import QtQuick.Layouts  1.0
import QtQuick.Controls 2.3

import mmm 1.0


ApplicationWindow { 
    Component.onCompleted:{
        console.log("checking if values are correct:")
        console.log("B.FOO should be = 1000", B.FOO)
        console.log("B.BAR should be = 1111", B.BAR)
    }
}

And here is a main file to run it all:

main.cpp

#include <QGuiApplication>

#include <QtQml/QQmlApplicationEngine>
#include <QtQuick/QQuickWindow>

#include <QObject>
#include <QDebug>
#include "b.h"

int main(int argc, char *argv[])
{
    qmlRegisterUncreatableType<B>("mmm",1, 0, "B", "err");

    // (check qDebug capabilities that are coded inside the 
    B b; consturctor)

    // checking enum inside qml
    QGuiApplication a(argc, argv);
    QQmlApplicationEngine eng(QUrl("qrc:/qml/MainWindow.qml"));
    QQuickWindow* window = qobject_cast<QQuickWindow*>(eng.rootObjects().first());
    window->show();

    return a.exec();
}

and the result is

enums from A 1000 1001 1002
enums from B B::E_BAR(BAR) B::E_BAR(BARR) B::E_BAR(BARRR)
qml: checking if values are correct:
qml: B.FOO should be = 1000 undefined
qml: B.BAR should be = 1111 1111

So:

  • new feature of Q_ENUM (name printing in qDebug) does not work
  • old Q_ENUMS does not work too
  • value in qml is undefined
  • normal enum (that is not from a base class) is working as expected

I tried making an alias type (using E_FOO_FORWARDED = A::E_FOO) with same results. Is there a solution for this problem?


Additional files for the project

inherited_enum.pro

QT += gui core qml quick

TEMPLATE = app
CONFIG += c++14 console qml
SOURCES += main.cpp 
RESOURCES += qml.qrc

qml.qrc

<RCC>
    <qresource prefix="/qml">
        <file>MainWindow.qml</file>
    </qresource>
</RCC>
2
  • I guess the problem could be solved be deriving the base class from QObject and defining the enum there. Commented Jul 24, 2018 at 10:15
  • Yes, but I wanted the base class to be as lean as possible. I ended up declaring "forwarded" enum like enum E_FOO_FORWARDED{F_FOO = A::FOO, ...} Commented Jul 24, 2018 at 10:23

1 Answer 1

1

Qt extensions like Q_ENUM are handled by macros and moc, which only handle a required subset of C++. It does not really handle inheritance, and only works on the current class definition.

As a consequence, you have to put your Q_ENUMS in the defining class of the underlying enum.

Sign up to request clarification or add additional context in comments.

1 Comment

I feel like there should be some kind of error message or at least warning. B::FOO is visible from the class so I suppose it's moc where the problem is. I tried to overcome this by alias type but it's probably not supported either (as you mentioned).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.