47

I am trying to use the Qt reflection for converting enum to QString.

Here is the part of code:

class ModelApple
{
    Q_GADGET
    Q_ENUMS(AppleType)
public:
    enum AppleType {
      Big,
      Small
    }
}

And here is i trying to do:

convertEnumToQString(ModelApple::Big)

Return "Big"

Is this possible? If you have any idea about convertEnumToQString, please share it

aurelien
  • 404
  • 4
  • 22
JustWe
  • 4,250
  • 3
  • 39
  • 90

6 Answers6

79

You need to use Q_ENUM macro, which registers an enum type with the meta-object system.

enum AppleType {
  Big,
  Small
};
Q_ENUM(AppleType)

And now you can use the QMetaEnum class to access meta-data about an enumerator.

QMetaEnum metaEnum = QMetaEnum::fromType<ModelApple::AppleType>();
qDebug() << metaEnum.valueToKey(ModelApple::Big);

Here is a generic template for such utility:

template<typename QEnum>
std::string QtEnumToString (const QEnum value)
{
  return std::string(QMetaEnum::fromType<QEnum>().valueToKey(value));
}
iammilind
  • 68,093
  • 33
  • 169
  • 336
Meefte
  • 6,469
  • 1
  • 39
  • 42
  • 8
    `QMetaEnum::fromType` is available from Qt 5, it doesn't exist in Qt 4. You should add this remark. By the way, I don't recommend to use `QMetaEnum::key` since it take `index` as parameter, how come is he declared `enum AppleType { Big = 2, Small}` – Danh Dec 15 '15 at 05:58
  • 4
    From the docs, it looks like this is actually only available from Qt 5.5 thus I still need to use my method in the answer I gave (was about to update my code but have to use Qt 5.4 for now). – CJCombrink Dec 15 '15 at 06:27
  • 'keyToValue()' can do the other way around: get the enum value from the string! – jaques-sam Dec 11 '18 at 12:58
  • I got this: undefined reference to MyClass::staticMetaObject . I copied the example from official page of Q_ENUM . – SuB Dec 02 '20 at 08:01
40

Much more elegant way found (Qt 5.9), just one single line, with the help of mighty QVariant.

turns enum into string:

QString theBig = QVariant::fromValue(ModelApple::Big).toString();

Perhaps you don't need QMetaEnum anymore.

Sample code here:

ModelApple (no need to claim Q_DECLARE_METATYE)

class ModelApple : public QObject
{
    Q_OBJECT
public:
    enum AppleType {
      Big,
      Small
    };
    Q_ENUM(AppleType)
    explicit ModelApple(QObject *parent = nullptr);
};

And I create a widget application, calling QVaraint function there :

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <modelapple.h>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QString s = QVariant::fromValue(ModelApple::Big).toString();
    qDebug() << s;

}

MainWindow::~MainWindow()
{
    delete ui;
}

You can see that i try to output the string on console , which really did: enter image description here

And sorry for reverse casting , i tried successfully in some project , but some how this time i met compiling error. So i decide to remove it from my answer.

jaques-sam
  • 2,578
  • 1
  • 26
  • 24
Ju-Hsien Lai
  • 643
  • 7
  • 14
  • 1
    Thanks for answering, looks like the method needs to add `Q_DECLARE_METATYPE(ModelApple::AppleType)`, and even added make it compiled successful, the result is an empty string. Could you please post the example code for this? – JustWe Nov 20 '17 at 00:51
  • For anyone struggling with this solution: you need Q_OBJECT and Q_ENUM. Also your enum has to be public. – Cheesi Feb 20 '19 at 11:54
  • 1
    @Cheesi you don't need `Q_OBJECT`: `Q_GADGET` is sufficient for this (unless you are really making a `QObject`). – Ruslan Aug 19 '19 at 12:21
9

The following should get you going:

QString convertEnumToQString(ModelApple::AppleType type) {
    const QMetaObject metaObject = ModelApple::staticMetaObject;
    int enumIndex = metaObject.indexOfEnumerator("AppleType");
    if(enumIndex == -1) {
        /* The enum does not contain the specified enum */
        return "";
    }
    QMetaEnum en = metaObject.enumerator(enumIndex);
    return QString(en.valueToKey(type));
}
CJCombrink
  • 3,738
  • 1
  • 22
  • 38
  • Why don't you join the declaration of `enumString` and `enumString = en.valueToKey(type);` it will call only 1 constructor instead of 1 constructor and 1 `operator =`. Also, we can eliminate the check with `-1` since we can sure that that enum is existed. – Danh Dec 15 '15 at 05:54
  • So i have to specify the enumerator "AppleType" ? – JustWe Dec 15 '15 at 05:56
  • @Danh Yes you can do that. My actual code is a template function that takes in the enum name and the enum value to return the string. I modified it to answer the question. My usage is `string = convertEnumToQString("AppleType", ModelApple::Big);` so I need to check for a valid enum and assert if not valid for debugging. Also I assert before the return thus the reason for first assigning and then returning (purely for debugging). – CJCombrink Dec 15 '15 at 06:23
  • 1
    I get the the point for the template. Regarding the declaration, assign, and return, I still think that we shouldn't take an extra step, – Danh Dec 15 '15 at 06:28
  • @user3308570 Unfortunately yes unless you have Qt 5.5 (then you can use the other answer) that is why I suggest adding the check for in case you decide to change the name of the enum in future. – CJCombrink Dec 15 '15 at 06:41
  • Okay,unfortunately i am using Qt 5.3. Thanks guys. – JustWe Dec 15 '15 at 07:01
7

For the global Enum declaring use this in any header file:

namespace YourNamespace {

Q_NAMESPACE

enum YourEnum: int {

    EnumValue1,
    EnumValue2
};
Q_ENUM_NS(YourEnum)

}

and this where you want to get Enum description:

QMetaEnum metaEnum = QMetaEnum::fromType<YourEnum>();
qDebug() << "Enum description: " << metaEnum.name() << "::" << metaEnum.valueToKey(YourEnum::EnumValue2);
  • 1
    I had tried to get this to work numerous times over the years, and recently I tried your solution, and was successful! The trick was wrapping my "global" enum (ie: not contained within a class) inside a namespace. Thanks! – Doug Dec 07 '20 at 19:18
  • 1
    Such a helpful answer. Thank you!! – developer01 Oct 07 '21 at 21:11
2

How about:

QString convertEnumToQString(ModelApple::AppleType type)
{
    const QMetaObject &mo = ModelApple::staticMetaObject;
    int index = mo.indexOfEnumerator("AppleType");
    QMetaEnum metaEnum = mo.enumerator(index);
    return metaEnum.valueToKey(type);
}

UPDATED: For Qt 5.5, see this answer

Community
  • 1
  • 1
Danh
  • 5,916
  • 7
  • 30
  • 45
2

I faced the same problem and this is how i solved it. This is especially for Qt 4.8

QString string = enumToString(ModelApple::Big);

QString ModelApple::enumToString(AppleType apple)
{
    int index = metaObject()->indexOfEnumerator("AppleType");
    QMetaEnum metaEnum = metaObject()->enumerator(index);
    return metaEnum.valueToKey(apple);
}
secretgenes
  • 1,291
  • 1
  • 19
  • 39