AusweisApp2/src/global/EnumHelper.h

188 lines
3.7 KiB
C++

/*!
* \brief Helper class to provide a QMetaObject handler for enumerations.
*
* \copyright Copyright (c) 2014-2019 Governikus GmbH & Co. KG, Germany
*/
#pragma once
#include <QDebug>
#include <QMetaEnum>
#include <type_traits>
namespace governikus
{
#define defineEnumOperators(enumName)\
inline QDebug operator<<(QDebug pDbg, enumName pType)\
{\
QDebugStateSaver saver(pDbg);\
return pDbg.noquote() << Enum<enumName>::getName(pType);\
}\
\
inline QString& operator+=(QString & pStr, enumName pType)\
{\
pStr += Enum<enumName>::getName(pType);\
return pStr;\
}\
\
inline QString operator+(const QString& pStr, enumName pType)\
{\
return pStr + Enum<enumName>::getName(pType);\
}\
\
inline QString operator+(enumName pType, const QString& pStr)\
{\
return Enum<enumName>::getName(pType) + pStr;\
}\
\
inline bool operator==(std::underlying_type<enumName>::type pType, enumName pName)\
{\
return static_cast<std::underlying_type<enumName>::type>(pName) == pType;\
}\
inline bool operator!=(std::underlying_type<enumName>::type pType, enumName pName)\
{\
return !(pType == pName);\
}\
\
inline uint qHash(enumName pKey, uint pSeed)\
{\
return ::qHash(static_cast<std::underlying_type<enumName>::type>(pKey), pSeed);\
}
#define defineTypedEnumType(enumName, enumType, ...)\
class Enum##enumName\
{\
Q_GADGET\
private:\
Enum##enumName();\
Q_DISABLE_COPY(Enum##enumName)\
\
public:\
enum class enumName : enumType\
{\
__VA_ARGS__\
};\
\
Q_ENUM(enumName)\
};\
\
using enumName = Enum##enumName::enumName;\
\
defineEnumOperators(enumName)
#define defineEnumType(enumName, ...) defineTypedEnumType(enumName, int, __VA_ARGS__)
template<typename EnumTypeT> class Enum
{
using EnumBaseTypeT = typename std::underlying_type<EnumTypeT>::type;
private:
Enum() = delete;
Q_DISABLE_COPY(Enum)
public:
static inline QMetaEnum getQtEnumMetaEnum()
{
return QMetaEnum::fromType<EnumTypeT>();
}
static QLatin1String getName()
{
return QLatin1String(getQtEnumMetaEnum().name());
}
static QLatin1String getName(EnumTypeT pType)
{
const int value = static_cast<int>(pType);
const char* const name = getQtEnumMetaEnum().valueToKey(value);
if (Q_UNLIKELY(name == nullptr))
{
qCritical().noquote().nospace() << "CRITICAL CONVERSION MISMATCH: UNKNOWN 0x" << QString::number(value, 16);
return QLatin1String();
}
return QLatin1String(name);
}
static int getCount()
{
return getQtEnumMetaEnum().keyCount();
}
static QVector<EnumTypeT> getList()
{
QVector<EnumTypeT> list;
const QMetaEnum metaEnum = getQtEnumMetaEnum();
list.reserve(metaEnum.keyCount());
for (int i = 0; i < metaEnum.keyCount(); ++i)
{
list << static_cast<EnumTypeT>(metaEnum.value(i));
}
return list;
}
static EnumTypeT fromString(const char* const pValue, EnumTypeT pDefault)
{
bool ok = false;
int key = getQtEnumMetaEnum().keyToValue(pValue, &ok);
if (ok)
{
return static_cast<EnumTypeT>(key);
}
return pDefault;
}
static EnumTypeT fromString(const QString& pValue, EnumTypeT pDefaultType)
{
return fromString(pValue.toUtf8().constData(), pDefaultType);
}
static bool isValue(int pValue)
{
return getQtEnumMetaEnum().valueToKey(pValue) != nullptr;
}
static bool isValue(uchar pValue)
{
return isValue(static_cast<int>(pValue));
}
static bool isValue(char pValue)
{
return isValue(static_cast<uchar>(pValue));
}
static EnumBaseTypeT getValue(EnumTypeT pType)
{
return static_cast<EnumBaseTypeT>(pType);
}
};
template<typename T> inline QLatin1String getEnumName(T pType)
{
return Enum<T>::getName(pType);
}
} // namespace governikus