Nils Nils - 2 months ago 34
C++ Question

Qt, QVariant, JSON and enums

I am trying to figure out how I am supposed to use enumerations in Qt so that I pack them in a QVariant and convert them to a QJsonValue and later JSON.

Following the docs I ended up declaring my enums:

enum BeautifulColors { Red, Green, Blue };
Q_DECLARE_METATYPE(BeautifulColors);


That way I can use
setValue(..)
on
QVariant
to set my custom defined enums as value.

The problem however is
QJsonValue::fromVariant()
, the docs says:


Converts variant to a QJsonValue and returns it. (...)
For all other QVariant types a conversion to a QString will be
attempted. If the returned string is empty, a Null QJsonValue will be
stored, otherwise a String value using the returned QString.


The conversion to
QString
fails and and my
QJsonValue
object ends up being Null.

Following the documentation further is confusing: There is a
Q_EUM
macro for enumeration definition within QObject. However since QObject is non-copy able I don't think QVariant is supposed to hold it. There are certainly some hacky was to get it working, but that is not what I am looking for. What is the recommended way in Qt to define enums so that they can be used as datatypes and converted into JSON and read from JSON?

Update

Tried the following:

rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H

#include <QObject>

class Rectangle : public QObject
{
Q_OBJECT

public:

enum Color
{
Red,
Green,
Blue,
};

Q_ENUM(Color)

Rectangle(double x, double y, Color color, QObject *parent = 0);

private:

double _x;
double _y;
Color _color;
};

#endif

rectangle.cpp
#include "rectangle.h"

Rectangle::Rectangle(double x, double y, Rectangle::Color color, QObject *parent)
: QObject(parent)
, _x(x)
, _y(y)
, _color(color)
{

}

main.cpp
#include <QVariant>
#include <QDebug>
#include <QString>

#include "rectangle.h"
int main(int argc, char *argv[])
{
int id = qMetaTypeId<Rectangle::Color>();
Rectangle::Color blueColor = Rectangle::Blue;
QVariant myVariant;
myVariant.setValue(blueColor);
qDebug() << id;
qDebug() << myVariant.toString();
}


Now it has a typ id and a string representation! But not the class holding it:

int idRectangle = qMetaTypeId<Rectangle>();


Does not compile and I cannot register it with
Q_DECLARE_MEATYPE
, because it does not have a constructor. What if I need QVariants toString() to work with any class?

Second Update

Using the Q_GADGET macro I now get a (different) type id for the enum and the class holding it. However I still only get a string representation for the enum.

Answer

Q_ENUM or Q_ENUMS are needed to generate the necessary QMetaEnum structure to toString/fromString functionality.

They need to be placed in a QObject derived class with the Q_OBJECT marker or in any class with the Q_GADGET marker in order for moc to process them and generate the necessary code.

The class they are defined in is not the one being stored in the variant though when you store an enum value. You can consider this class more like a "namespace" for your enum.

Comments