Skip to content

Commit

Permalink
add QMetaEnum usage for autogenerated code
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksandr Kunichik authored and Oleksandr Kunichik committed Oct 22, 2020
1 parent 8f4d2e9 commit 8597edf
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 70 deletions.
35 changes: 9 additions & 26 deletions codegen/facelift/templates/Enum.template.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,37 +74,20 @@ template<> inline const std::initializer_list<{{enum.fullyQualifiedCppType}}>& v
return values;
}

template <> inline QString enumToString(const {{enum.fullyQualifiedCppType}}& v)
{
const char* s = "Invalid";
switch(v) {
{% for member in enum.members %}
case {{enum.fullyQualifiedCppType}}::{{member}}:
s = "{{member}}";
break;
{% endfor %}
default:
break;
}
return s;
}

}
} // end namespace facelift


inline void assignFromString(const QString &s, {{enum.fullyQualifiedCppType}}& v)
inline void fromString(const QString& string, {{enum.fullyQualifiedCppType}}& value)
{
{% for member in enum.members %}
if (s == "{{member}}")
v = {{enum.fullyQualifiedCppType}}::{{member}};
else
{% endfor %}
::facelift::onAssignFromStringError(s);
auto valuePointer = facelift::Enum::fromString<{{enum.fullyQualifiedCppType}}>(string);
if(!valuePointer) {
facelift::Enum::fromStringError(string);
}
value = *valuePointer;
}


inline QTextStream &operator <<(QTextStream &outStream, const {{enum.fullyQualifiedCppType}}& f)
inline QTextStream &operator <<(QTextStream& outStream, const {{enum.fullyQualifiedCppType}}& value)
{
outStream << facelift::enumToString(f);
outStream << facelift::Enum::toString(value);
return outStream;
}
9 changes: 0 additions & 9 deletions src/model/FaceliftCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,6 @@ inline const std::initializer_list<Type> &validValues()
return l;
}


template<typename Type>
QString enumToString(const Type &v)
{
Q_UNUSED(v);
static_assert(!std::is_enum<Type>::value, "Missing specialization of enumToString() template");
return "";
}

#ifdef QT_DEBUG
#define faceliftSeriousError qFatal
#else
Expand Down
11 changes: 8 additions & 3 deletions src/model/FaceliftEnum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@
#include <QDebug>

namespace facelift {

namespace Enum {

void onAssignFromStringError(const QString &s)
void fromStringError(const QString &string)
{
qFatal("No enum value matching string %s", qPrintable(s));
qFatal("No enum value matching string %s", qPrintable(string));
}

}

} // end namespace Enum

} // end namespace facelift
36 changes: 33 additions & 3 deletions src/model/FaceliftEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,41 @@
#pragma once

#include "FaceliftCommon.h"
#include <QObject>
#include <QTextStream>
#include <type_traits>
#include <memory>
#include <QString>
#include <QMetaEnum>
#include <QByteArray>

namespace facelift {

void onAssignFromStringError(const QString &s);
namespace Enum {

void fromStringError(const QString &string);

// Returns the string that is used as the name of the given enumeration value,
// or an empty string if value is not defined
template<class T, std::enable_if_t<QtPrivate::IsQEnumHelper<T>::Value, T>* = nullptr>
QString toString(T value)
{
return QMetaEnum::fromType<T>().valueToKey(static_cast<int>(value));
}

// Returns the enumaration value of the given enumeration key, or nullptr if key is not defined.
// TODO change std::unique_ptr to std::optional when it will be possible
template<typename T>
std::unique_ptr<T> fromString(const QString &string)
{
QByteArray byteArray = string.toLocal8Bit();
bool ok {};
int value = QMetaEnum::fromType<T>().keyToValue(byteArray.data(), &ok);

T result = static_cast<T>(value);

return ok ? std::make_unique<T>(result) : nullptr;
}


} // end namespace Enum

} // end namespace facelift
57 changes: 28 additions & 29 deletions src/model/StringConversionHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,17 @@
#include <QList>
#include <type_traits>
#include "FaceliftCommon.h"
#include "FaceliftEnum.h"

namespace facelift {

class InterfaceBase;
class StructureBase;

template<typename Type, typename Enable = void>
template<typename T, typename Enable = void>
struct StringConversionHandler
{
typedef Type QMLType;

static QString toString(const Type &v)
static QString toString(const T &v)
{
QString s;
QTextStream(&s) << v;
Expand All @@ -65,77 +64,77 @@ struct StringConversionHandler<QVariant>
}
};

QString qObjectToString(const QObject *o);
QString qObjectToString(const QObject *object);

template<typename Type>
struct StringConversionHandler<Type *, typename std::enable_if<std::is_base_of<InterfaceBase, Type>::value>::type>
template<typename T>
struct StringConversionHandler<T*, std::enable_if_t<std::is_base_of<InterfaceBase, T>::value>>
{
static QString toString(const Type *o)
static QString toString(const T *object)
{
return qObjectToString(o);
return qObjectToString(object);
}
};


template<typename Type>
struct StringConversionHandler<Type, typename std::enable_if<std::is_base_of<StructureBase, Type>::value>::type>
template<typename T>
struct StringConversionHandler<T, std::enable_if_t<std::is_base_of<StructureBase, T>::value>>
{
static QString toString(const Type &v)
static QString toString(const T &value)
{
return v.toString();
return value.toString();
}
};


template<typename Type>
struct StringConversionHandler<Type, typename std::enable_if<std::is_enum<Type>::value>::type>
template<typename T>
struct StringConversionHandler<T, std::enable_if_t<QtPrivate::IsQEnumHelper<T>::Value, T>>
{
static QString toString(const Type &v)
static QString toString(T value)
{
return facelift::enumToString(v);
return Enum::toString(value);
}
};

template<typename ElementType>
struct StringConversionHandler<QList<ElementType> >
template<typename T>
struct StringConversionHandler<QList<T> >
{
static QString toString(const QList<ElementType> &v)
static QString toString(const QList<T> &v)
{
QString s;
QTextStream str(&s);
str << "[ ";
for (const auto &element : v) {
str << StringConversionHandler<ElementType>::toString(element);
str << StringConversionHandler<T>::toString(element);
str << ", ";
}
str << "]";
return s;
}
};

template<typename ElementType>
struct StringConversionHandler<QMap<QString, ElementType> >
template<typename T>
struct StringConversionHandler<QMap<QString, T> >
{
static QString toString(const QMap<QString, ElementType> &map)
static QString toString(const QMap<QString, T> &map)
{
QString s;
QTextStream str(&s);
str << "[ ";
for (auto i = map.constBegin(); i != map.constEnd(); ++i) {
str << StringConversionHandler<QString>::toString(i.key());
str << ":";
str << StringConversionHandler<ElementType>::toString(i.value());
str << StringConversionHandler<T>::toString(i.value());
str << ", ";
}
str << "]";
return s;
}
};

template<typename Type>
inline QString toString(const Type &v)
template<typename T>
inline QString toString(const T &v)
{
return StringConversionHandler<Type>::toString(v);
return StringConversionHandler<T>::toString(v);
}


}

0 comments on commit 8597edf

Please sign in to comment.