Fix QMetaObject naming of class enum flag
Adds an enumName to QMetaEnum to carry the name of the enum since for flags that doesn't match the name of the Qt type, but is needed if the flag is scoped. Change-Id: I1c0f77eb9e40e6fd1eb6a59bea77caf0f33fcf43 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
parent
8f58e1319c
commit
1c623bc6d1
@ -946,7 +946,7 @@ QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *met
|
||||
if (const char *scope = me.scope())
|
||||
dbg << scope << "::";
|
||||
if (me.isScoped())
|
||||
dbg << name << "::";
|
||||
dbg << me.enumName() << "::";
|
||||
dbg << key;
|
||||
} else {
|
||||
dbg << meta->className() << "::" << name << "(" << value << ")";
|
||||
@ -964,7 +964,7 @@ QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaO
|
||||
const QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
|
||||
if (const char *scope = me.scope())
|
||||
debug << scope << "::";
|
||||
debug << me.name() << ">(" << me.valueToKeys(value) << ')';
|
||||
debug << me.enumName() << ">(" << me.valueToKeys(value) << ')';
|
||||
return debug;
|
||||
}
|
||||
#endif // !QT_NO_QOBJECT
|
||||
|
@ -968,10 +968,24 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co
|
||||
int QMetaObject::indexOfEnumerator(const char *name) const
|
||||
{
|
||||
const QMetaObject *m = this;
|
||||
const int intsPerEnum = priv(m->d.data)->revision >= 8 ? 5 : 4;
|
||||
while (m) {
|
||||
const QMetaObjectPrivate *d = priv(m->d.data);
|
||||
for (int i = d->enumeratorCount - 1; i >= 0; --i) {
|
||||
const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]);
|
||||
const char *prop = rawStringData(m, m->d.data[d->enumeratorData + intsPerEnum * i]);
|
||||
if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
|
||||
i += m->enumeratorOffset();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
m = m->d.superdata;
|
||||
}
|
||||
// Check alias names:
|
||||
m = this;
|
||||
while (m) {
|
||||
const QMetaObjectPrivate *d = priv(m->d.data);
|
||||
for (int i = d->enumeratorCount - 1; i >= 0; --i) {
|
||||
const char *prop = rawStringData(m, m->d.data[d->enumeratorData + intsPerEnum * i + 1]);
|
||||
if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
|
||||
i += m->enumeratorOffset();
|
||||
return i;
|
||||
@ -1086,10 +1100,11 @@ QMetaEnum QMetaObject::enumerator(int index) const
|
||||
if (i < 0 && d.superdata)
|
||||
return d.superdata->enumerator(index);
|
||||
|
||||
const int intsPerEnum = priv(d.data)->revision >= 8 ? 5 : 4;
|
||||
QMetaEnum result;
|
||||
if (i >= 0 && i < priv(d.data)->enumeratorCount) {
|
||||
result.mobj = this;
|
||||
result.handle = priv(d.data)->enumeratorData + 4*i;
|
||||
result.handle = priv(d.data)->enumeratorData + intsPerEnum * i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -2552,12 +2567,15 @@ bool QMetaMethod::invokeOnGadget(void* gadget, QGenericReturnArgument returnValu
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the name of the enumerator (without the scope).
|
||||
Returns the name of the type (without the scope).
|
||||
|
||||
For example, the Qt::AlignmentFlag enumeration has \c
|
||||
AlignmentFlag as the name and \l Qt as the scope.
|
||||
For example, the Qt::Key enumeration has \c
|
||||
Key as the type name and \l Qt as the scope.
|
||||
|
||||
\sa isValid(), scope()
|
||||
For flags this returns the name of the flag type, not the
|
||||
name of the enum type.
|
||||
|
||||
\sa isValid(), scope(), enumName()
|
||||
*/
|
||||
const char *QMetaEnum::name() const
|
||||
{
|
||||
@ -2566,6 +2584,28 @@ const char *QMetaEnum::name() const
|
||||
return rawStringData(mobj, mobj->d.data[handle]);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the enum name of the flag (without the scope).
|
||||
|
||||
For example, the Qt::AlignmentFlag flag has \c
|
||||
AlignmentFlag as the enum name, but \c Alignment as as the type name.
|
||||
Non flag enums has the same type and enum names.
|
||||
|
||||
Enum names have the same scope as the type name.
|
||||
|
||||
\since 5.12
|
||||
\sa isValid(), name()
|
||||
*/
|
||||
const char *QMetaEnum::enumName() const
|
||||
{
|
||||
if (!mobj)
|
||||
return 0;
|
||||
const bool rev8p = priv(mobj->d.data)->revision >= 8;
|
||||
if (rev8p)
|
||||
return rawStringData(mobj, mobj->d.data[handle + 1]);
|
||||
return name();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of keys.
|
||||
|
||||
@ -2575,10 +2615,10 @@ int QMetaEnum::keyCount() const
|
||||
{
|
||||
if (!mobj)
|
||||
return 0;
|
||||
return mobj->d.data[handle + 2];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
return mobj->d.data[handle + offset];
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns the key with the given \a index, or 0 if no such key exists.
|
||||
|
||||
@ -2588,8 +2628,9 @@ const char *QMetaEnum::key(int index) const
|
||||
{
|
||||
if (!mobj)
|
||||
return 0;
|
||||
int count = mobj->d.data[handle + 2];
|
||||
int data = mobj->d.data[handle + 3];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
int count = mobj->d.data[handle + offset];
|
||||
int data = mobj->d.data[handle + offset + 1];
|
||||
if (index >= 0 && index < count)
|
||||
return rawStringData(mobj, mobj->d.data[data + 2*index]);
|
||||
return 0;
|
||||
@ -2605,8 +2646,9 @@ int QMetaEnum::value(int index) const
|
||||
{
|
||||
if (!mobj)
|
||||
return 0;
|
||||
int count = mobj->d.data[handle + 2];
|
||||
int data = mobj->d.data[handle + 3];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
int count = mobj->d.data[handle + offset];
|
||||
int data = mobj->d.data[handle + offset + 1];
|
||||
if (index >= 0 && index < count)
|
||||
return mobj->d.data[data + 2*index + 1];
|
||||
return -1;
|
||||
@ -2624,7 +2666,8 @@ int QMetaEnum::value(int index) const
|
||||
*/
|
||||
bool QMetaEnum::isFlag() const
|
||||
{
|
||||
return mobj && mobj->d.data[handle + 1] & EnumIsFlag;
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
|
||||
return mobj && mobj->d.data[handle + offset] & EnumIsFlag;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2635,7 +2678,8 @@ bool QMetaEnum::isFlag() const
|
||||
*/
|
||||
bool QMetaEnum::isScoped() const
|
||||
{
|
||||
return mobj && mobj->d.data[handle + 1] & EnumIsScoped;
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 2 : 1;
|
||||
return mobj && mobj->d.data[handle + offset] & EnumIsScoped;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -2677,8 +2721,9 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
|
||||
scope = s - key - 1;
|
||||
key += scope + 2;
|
||||
}
|
||||
int count = mobj->d.data[handle + 2];
|
||||
int data = mobj->d.data[handle + 3];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
int count = mobj->d.data[handle + offset];
|
||||
int data = mobj->d.data[handle + offset + 1];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
|
||||
if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
|
||||
@ -2703,8 +2748,9 @@ const char* QMetaEnum::valueToKey(int value) const
|
||||
{
|
||||
if (!mobj)
|
||||
return 0;
|
||||
int count = mobj->d.data[handle + 2];
|
||||
int data = mobj->d.data[handle + 3];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
int count = mobj->d.data[handle + offset];
|
||||
int data = mobj->d.data[handle + offset + 1];
|
||||
for (int i = 0; i < count; ++i)
|
||||
if (value == (int)mobj->d.data[data + 2*i + 1])
|
||||
return rawStringData(mobj, mobj->d.data[data + 2*i]);
|
||||
@ -2735,8 +2781,9 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
|
||||
return 0;
|
||||
// ### TODO write proper code: do not allocate memory, so we can go nothrow
|
||||
int value = 0;
|
||||
int count = mobj->d.data[handle + 2];
|
||||
int data = mobj->d.data[handle + 3];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
int count = mobj->d.data[handle + offset];
|
||||
int data = mobj->d.data[handle + offset + 1];
|
||||
for (const QStringRef &untrimmed : splitKeys) {
|
||||
const QStringRef trimmed = untrimmed.trimmed();
|
||||
QByteArray qualified_key = trimmed.toLatin1();
|
||||
@ -2778,8 +2825,9 @@ QByteArray QMetaEnum::valueToKeys(int value) const
|
||||
QByteArray keys;
|
||||
if (!mobj)
|
||||
return keys;
|
||||
int count = mobj->d.data[handle + 2];
|
||||
int data = mobj->d.data[handle + 3];
|
||||
const int offset = priv(mobj->d.data)->revision >= 8 ? 3 : 2;
|
||||
int count = mobj->d.data[handle + offset];
|
||||
int data = mobj->d.data[handle + offset + 1];
|
||||
int v = value;
|
||||
// reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
|
||||
for (int i = count - 1; i >= 0; --i) {
|
||||
|
@ -209,6 +209,7 @@ public:
|
||||
Q_DECL_CONSTEXPR inline QMetaEnum() : mobj(nullptr), handle(0) {}
|
||||
|
||||
const char *name() const;
|
||||
const char *enumName() const;
|
||||
bool isFlag() const;
|
||||
bool isScoped() const;
|
||||
|
||||
|
@ -171,7 +171,8 @@ class QMutex;
|
||||
struct QMetaObjectPrivate
|
||||
{
|
||||
// revision 7 is Qt 5.0 everything lower is not supported
|
||||
enum { OutputRevision = 7 }; // Used by moc, qmetaobjectbuilder and qdbus
|
||||
// revision 8 is Qt 5.12: It adds the enum name to QMetaEnum
|
||||
enum { OutputRevision = 8 }; // Used by moc, qmetaobjectbuilder and qdbus
|
||||
|
||||
int revision;
|
||||
int className;
|
||||
|
@ -190,11 +190,12 @@ class QMetaEnumBuilderPrivate
|
||||
{
|
||||
public:
|
||||
QMetaEnumBuilderPrivate(const QByteArray& _name)
|
||||
: name(_name), isFlag(false), isScoped(false)
|
||||
: name(_name), enumName(_name), isFlag(false), isScoped(false)
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray name;
|
||||
QByteArray enumName;
|
||||
bool isFlag;
|
||||
bool isScoped;
|
||||
QList<QByteArray> keys;
|
||||
@ -637,6 +638,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QByteArray& name)
|
||||
QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
|
||||
{
|
||||
QMetaEnumBuilder en = addEnumerator(prototype.name());
|
||||
en.setEnumName(prototype.enumName());
|
||||
en.setIsFlag(prototype.isFlag());
|
||||
en.setIsScoped(prototype.isScoped());
|
||||
int count = prototype.keyCount();
|
||||
@ -1216,7 +1218,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
- int(d->methods.size()) // return "parameters" don't have names
|
||||
- int(d->constructors.size()); // "this" parameters don't have names
|
||||
if (buf) {
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QMetaObjectBuilder should generate the same version as moc");
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QMetaObjectBuilder should generate the same version as moc");
|
||||
pmeta->revision = QMetaObjectPrivate::OutputRevision;
|
||||
pmeta->flags = d->flags;
|
||||
pmeta->className = 0; // Class name is always the first string.
|
||||
@ -1244,7 +1246,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
|
||||
pmeta->enumeratorCount = int(d->enumerators.size());
|
||||
pmeta->enumeratorData = dataIndex;
|
||||
dataIndex += 4 * int(d->enumerators.size());
|
||||
dataIndex += 5 * int(d->enumerators.size());
|
||||
|
||||
pmeta->constructorCount = int(d->constructors.size());
|
||||
pmeta->constructorData = dataIndex;
|
||||
@ -1261,7 +1263,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
dataIndex += int(d->properties.size());
|
||||
if (hasRevisionedProperties)
|
||||
dataIndex += int(d->properties.size());
|
||||
dataIndex += 4 * int(d->enumerators.size());
|
||||
dataIndex += 5 * int(d->enumerators.size());
|
||||
dataIndex += 5 * int(d->constructors.size());
|
||||
}
|
||||
|
||||
@ -1410,15 +1412,17 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
|
||||
for (const auto &enumerator : d->enumerators) {
|
||||
int name = strings.enter(enumerator.name);
|
||||
int enumName = strings.enter(enumerator.enumName);
|
||||
int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
|
||||
int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
|
||||
int count = enumerator.keys.size();
|
||||
int enumOffset = enumIndex;
|
||||
if (buf) {
|
||||
data[dataIndex] = name;
|
||||
data[dataIndex + 1] = isFlag | isScoped;
|
||||
data[dataIndex + 2] = count;
|
||||
data[dataIndex + 3] = enumOffset;
|
||||
data[dataIndex + 1] = enumName;
|
||||
data[dataIndex + 2] = isFlag | isScoped;
|
||||
data[dataIndex + 3] = count;
|
||||
data[dataIndex + 4] = enumOffset;
|
||||
}
|
||||
for (int key = 0; key < count; ++key) {
|
||||
int keyIndex = strings.enter(enumerator.keys[key]);
|
||||
@ -1427,7 +1431,7 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
|
||||
data[enumOffset++] = enumerator.values[key];
|
||||
}
|
||||
}
|
||||
dataIndex += 4;
|
||||
dataIndex += 5;
|
||||
enumIndex += 2 * count;
|
||||
}
|
||||
|
||||
@ -2599,7 +2603,7 @@ QMetaEnumBuilderPrivate *QMetaEnumBuilder::d_func() const
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the name of the enumerator (without the scope).
|
||||
Returns the type name of the enumerator (without the scope).
|
||||
*/
|
||||
QByteArray QMetaEnumBuilder::name() const
|
||||
{
|
||||
@ -2610,6 +2614,33 @@ QByteArray QMetaEnumBuilder::name() const
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the enum name of the enumerator (without the scope).
|
||||
|
||||
\since 5.12
|
||||
*/
|
||||
QByteArray QMetaEnumBuilder::enumName() const
|
||||
{
|
||||
QMetaEnumBuilderPrivate *d = d_func();
|
||||
if (d)
|
||||
return d->enumName;
|
||||
else
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets this enumerator to have the enum name \c alias.
|
||||
|
||||
\since 5.12
|
||||
\sa isFlag(), enumName()
|
||||
*/
|
||||
void QMetaEnumBuilder::setEnumName(const QByteArray &alias)
|
||||
{
|
||||
QMetaEnumBuilderPrivate *d = d_func();
|
||||
if (d)
|
||||
d->enumName = alias;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if this enumerator is used as a flag; otherwise returns
|
||||
false.
|
||||
|
@ -297,6 +297,9 @@ public:
|
||||
|
||||
QByteArray name() const;
|
||||
|
||||
QByteArray enumName() const;
|
||||
void setEnumName(const QByteArray &alias);
|
||||
|
||||
bool isFlag() const;
|
||||
void setIsFlag(bool value);
|
||||
|
||||
|
@ -412,7 +412,7 @@ void QDBusMetaObjectGenerator::write(QDBusMetaObject *obj)
|
||||
- methods.count(); // ditto
|
||||
|
||||
QDBusMetaObjectPrivate *header = reinterpret_cast<QDBusMetaObjectPrivate *>(idata.data());
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 7, "QtDBus meta-object generator should generate the same version as moc");
|
||||
Q_STATIC_ASSERT_X(QMetaObjectPrivate::OutputRevision == 8, "QtDBus meta-object generator should generate the same version as moc");
|
||||
header->revision = QMetaObjectPrivate::OutputRevision;
|
||||
header->className = 0;
|
||||
header->classInfoCount = 0;
|
||||
|
@ -200,9 +200,9 @@ void Generator::generateCode()
|
||||
if (cdef->enumDeclarations.contains(def.name)) {
|
||||
enumList += def;
|
||||
}
|
||||
def.enumName = def.name;
|
||||
QByteArray alias = cdef->flagAliases.value(def.name);
|
||||
if (cdef->enumDeclarations.contains(alias)) {
|
||||
def.className = def.name;
|
||||
def.name = alias;
|
||||
enumList += def;
|
||||
}
|
||||
@ -370,7 +370,7 @@ void Generator::generateCode()
|
||||
|
||||
int enumsIndex = index;
|
||||
for (int i = 0; i < cdef->enumList.count(); ++i)
|
||||
index += 4 + (cdef->enumList.at(i).values.count() * 2);
|
||||
index += 5 + (cdef->enumList.at(i).values.count() * 2);
|
||||
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
|
||||
isConstructible ? index : 0);
|
||||
|
||||
@ -888,6 +888,8 @@ void Generator::registerEnumStrings()
|
||||
for (int i = 0; i < cdef->enumList.count(); ++i) {
|
||||
const EnumDef &e = cdef->enumList.at(i);
|
||||
strreg(e.name);
|
||||
if (!e.enumName.isNull())
|
||||
strreg(e.enumName);
|
||||
for (int j = 0; j < e.values.count(); ++j)
|
||||
strreg(e.values.at(j));
|
||||
}
|
||||
@ -898,8 +900,8 @@ void Generator::generateEnums(int index)
|
||||
if (cdef->enumDeclarations.isEmpty())
|
||||
return;
|
||||
|
||||
fprintf(out, "\n // enums: name, flags, count, data\n");
|
||||
index += 4 * cdef->enumList.count();
|
||||
fprintf(out, "\n // enums: name, alias, flags, count, data\n");
|
||||
index += 5 * cdef->enumList.count();
|
||||
int i;
|
||||
for (i = 0; i < cdef->enumList.count(); ++i) {
|
||||
const EnumDef &e = cdef->enumList.at(i);
|
||||
@ -908,8 +910,9 @@ void Generator::generateEnums(int index)
|
||||
flags |= EnumIsFlag;
|
||||
if (e.isEnumClass)
|
||||
flags |= EnumIsScoped;
|
||||
fprintf(out, " %4d, 0x%.1x, %4d, %4d,\n",
|
||||
fprintf(out, " %4d, %4d, 0x%.1x, %4d, %4d,\n",
|
||||
stridx(e.name),
|
||||
e.enumName.isNull() ? stridx(e.name) : stridx(e.enumName),
|
||||
flags,
|
||||
e.values.count(),
|
||||
index);
|
||||
@ -923,7 +926,7 @@ void Generator::generateEnums(int index)
|
||||
const QByteArray &val = e.values.at(j);
|
||||
QByteArray code = cdef->qualified.constData();
|
||||
if (e.isEnumClass)
|
||||
code += "::" + (e.className.isNull() ? e.name : e.className);
|
||||
code += "::" + (e.enumName.isNull() ? e.name : e.enumName);
|
||||
code += "::" + val;
|
||||
fprintf(out, " %4d, uint(%s),\n",
|
||||
stridx(val), code.constData());
|
||||
|
@ -64,7 +64,7 @@ Q_DECLARE_TYPEINFO(Type, Q_MOVABLE_TYPE);
|
||||
struct EnumDef
|
||||
{
|
||||
QByteArray name;
|
||||
QByteArray className;
|
||||
QByteArray enumName;
|
||||
QList<QByteArray> values;
|
||||
bool isEnumClass; // c++11 enum class
|
||||
EnumDef() : isEnumClass(false) {}
|
||||
|
@ -38,6 +38,13 @@
|
||||
class tst_QDebug: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum EnumType { EnumValue1 = 1, EnumValue2 = 2 };
|
||||
enum FlagType { EnumFlag1 = 1, EnumFlag2 = 2 };
|
||||
Q_ENUM(EnumType)
|
||||
Q_DECLARE_FLAGS(Flags, FlagType)
|
||||
Q_FLAG(Flags)
|
||||
|
||||
private slots:
|
||||
void assignment() const;
|
||||
void warningWithoutDebug() const;
|
||||
@ -637,6 +644,15 @@ void tst_QDebug::qDebugQFlags() const
|
||||
QCOMPARE(s_line, line);
|
||||
QCOMPARE(QString::fromLatin1(s_function), function);
|
||||
|
||||
// Test the output of QFlags with an enum not declared with Q_DECLARE_FLAGS and Q_FLAGS
|
||||
QFlags<EnumType> flags2(EnumValue2);
|
||||
qDebug() << flags2;
|
||||
QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::EnumType>(EnumValue2)"));
|
||||
|
||||
// A now for one that was fully declared
|
||||
tst_QDebug::Flags flags3(EnumFlag1);
|
||||
qDebug() << flags3;
|
||||
QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::FlagType>(EnumFlag1)"));
|
||||
}
|
||||
|
||||
void tst_QDebug::textStreamModifiers() const
|
||||
|
@ -37,7 +37,10 @@ class tst_QMetaEnum : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum SuperEnum { SuperValue1 = 1 , SuperValue2 = 2 };
|
||||
enum Flag { Flag1 = 1 , Flag2 = 2 };
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
Q_ENUM(SuperEnum)
|
||||
Q_FLAG(Flags)
|
||||
|
||||
private slots:
|
||||
void fromType();
|
||||
@ -49,7 +52,17 @@ void tst_QMetaEnum::fromType()
|
||||
{
|
||||
QMetaEnum meta = QMetaEnum::fromType<SuperEnum>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(!meta.isFlag());
|
||||
QCOMPARE(meta.name(), "SuperEnum");
|
||||
QCOMPARE(meta.enumName(), "SuperEnum");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 2);
|
||||
|
||||
meta = QMetaEnum::fromType<Flags>();
|
||||
QVERIFY(meta.isValid());
|
||||
QVERIFY(meta.isFlag());
|
||||
QCOMPARE(meta.name(), "Flags");
|
||||
QCOMPARE(meta.enumName(), "Flag");
|
||||
QCOMPARE(meta.enclosingMetaObject(), &staticMetaObject);
|
||||
QCOMPARE(meta.keyCount(), 2);
|
||||
}
|
||||
|
@ -69,7 +69,13 @@ namespace MyNamespace {
|
||||
MyFlag2 = 0x02,
|
||||
MyFlag3 = 0x04
|
||||
};
|
||||
enum class MyScopedFlag {
|
||||
MyFlag1 = 0x10,
|
||||
MyFlag2 = 0x20,
|
||||
MyFlag3 = 0x40
|
||||
};
|
||||
Q_DECLARE_FLAGS(MyFlags, MyFlag)
|
||||
Q_DECLARE_FLAGS(MyScopedFlags, MyScopedFlag)
|
||||
|
||||
MyEnum myEnum() const { return m_enum; }
|
||||
void setMyEnum(MyEnum val) { m_enum = val; }
|
||||
@ -87,6 +93,7 @@ namespace MyNamespace {
|
||||
Q_ENUM(MyScopedEnum)
|
||||
Q_ENUM(MyAnotherEnum)
|
||||
Q_FLAG(MyFlags)
|
||||
Q_FLAG(MyScopedFlags)
|
||||
|
||||
MyEnum m_enum;
|
||||
MyFlags m_flags;
|
||||
@ -1745,13 +1752,21 @@ void tst_QMetaObject::enumDebugStream()
|
||||
QTest::ignoreMessage(QtDebugMsg, "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint");
|
||||
qDebug() << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint;
|
||||
|
||||
QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) world");
|
||||
QTest::ignoreMessage(QtDebugMsg, "hello QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) world");
|
||||
MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1;
|
||||
qDebug() << "hello" << f1 << "world";
|
||||
|
||||
MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3;
|
||||
QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlags>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlags>(MyFlag2|MyFlag3)");
|
||||
QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)");
|
||||
qDebug() << f1 << f2;
|
||||
|
||||
QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)");
|
||||
MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2;
|
||||
qDebug() << f3;
|
||||
|
||||
QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2|MyFlag3)");
|
||||
f3 |= MyNamespace::MyClass::MyScopedFlag::MyFlag3;
|
||||
qDebug() << f3;
|
||||
}
|
||||
|
||||
void tst_QMetaObject::inherits_data()
|
||||
|
@ -830,6 +830,7 @@ void tst_QMetaObjectBuilder::enumerator()
|
||||
// Modify the attributes on enum1.
|
||||
enum1.setIsFlag(true);
|
||||
enum1.setIsScoped(true);
|
||||
enum1.setEnumName(QByteArrayLiteral("fooFlag"));
|
||||
QCOMPARE(enum1.addKey("ABC", 0), 0);
|
||||
QCOMPARE(enum1.addKey("DEF", 1), 1);
|
||||
QCOMPARE(enum1.addKey("GHI", -1), 2);
|
||||
@ -838,6 +839,7 @@ void tst_QMetaObjectBuilder::enumerator()
|
||||
QCOMPARE(enum1.name(), QByteArray("foo"));
|
||||
QVERIFY(enum1.isFlag());
|
||||
QVERIFY(enum1.isScoped());
|
||||
QCOMPARE(enum1.enumName(), QByteArray("fooFlag"));
|
||||
QCOMPARE(enum1.keyCount(), 3);
|
||||
QCOMPARE(enum1.index(), 0);
|
||||
QCOMPARE(enum1.key(0), QByteArray("ABC"));
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
enum TypedEnum : char { B0, B1 , B2, B3 };
|
||||
enum class TypedEnumClass : char { C0, C1, C2, C3 };
|
||||
enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
|
||||
enum class ClassFlag { F0, F1, F2, F3 };
|
||||
enum class ClassFlag { F0 = 1, F1 = 2, F2 = 4, F3 = 8};
|
||||
Q_DECLARE_FLAGS(ClassFlags, ClassFlag)
|
||||
|
||||
Q_ENUM(EnumClass)
|
||||
@ -58,7 +58,7 @@ public:
|
||||
enum TypedEnum : char { B0, B1 , B2, B3 };
|
||||
enum class TypedEnumClass : char { C0, C1, C2, C3 };
|
||||
enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
|
||||
enum class ClassFlag { F0, F1, F2, F3 };
|
||||
enum class ClassFlag { F0 = 1, F1 = 2, F2 = 4, F3 = 8 };
|
||||
Q_DECLARE_FLAGS(ClassFlags, ClassFlag)
|
||||
Q_ENUMS(EnumClass TypedEnum TypedEnumClass NormalEnum)
|
||||
Q_FLAGS(ClassFlags)
|
||||
|
@ -2248,6 +2248,7 @@ void tst_Moc::privateClass()
|
||||
void tst_Moc::cxx11Enums_data()
|
||||
{
|
||||
QTest::addColumn<const QMetaObject *>("meta");
|
||||
QTest::addColumn<QByteArray>("typeName");
|
||||
QTest::addColumn<QByteArray>("enumName");
|
||||
QTest::addColumn<char>("prefix");
|
||||
QTest::addColumn<bool>("isScoped");
|
||||
@ -2255,16 +2256,16 @@ void tst_Moc::cxx11Enums_data()
|
||||
const QMetaObject *meta1 = &CXX11Enums::staticMetaObject;
|
||||
const QMetaObject *meta2 = &CXX11Enums2::staticMetaObject;
|
||||
|
||||
QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << 'A' << true;
|
||||
QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << 'A' << true;
|
||||
QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << 'B' << false;
|
||||
QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << 'B' << false;
|
||||
QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << 'C' << true;
|
||||
QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << 'C' << true;
|
||||
QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << 'D' << false;
|
||||
QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << 'D' << false;
|
||||
QTest::newRow("ClassFlags") << meta1 << QByteArray("ClassFlags") << 'F' << true;
|
||||
QTest::newRow("ClassFlags 2") << meta2 << QByteArray("ClassFlags") << 'F' << true;
|
||||
QTest::newRow("EnumClass") << meta1 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
|
||||
QTest::newRow("EnumClass 2") << meta2 << QByteArray("EnumClass") << QByteArray("EnumClass") << 'A' << true;
|
||||
QTest::newRow("TypedEnum") << meta1 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
|
||||
QTest::newRow("TypedEnum 2") << meta2 << QByteArray("TypedEnum") << QByteArray("TypedEnum") << 'B' << false;
|
||||
QTest::newRow("TypedEnumClass") << meta1 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
|
||||
QTest::newRow("TypedEnumClass 2") << meta2 << QByteArray("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C' << true;
|
||||
QTest::newRow("NormalEnum") << meta1 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
|
||||
QTest::newRow("NormalEnum 2") << meta2 << QByteArray("NormalEnum") << QByteArray("NormalEnum") << 'D' << false;
|
||||
QTest::newRow("ClassFlags") << meta1 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
|
||||
QTest::newRow("ClassFlags 2") << meta2 << QByteArray("ClassFlags") << QByteArray("ClassFlag") << 'F' << true;
|
||||
}
|
||||
|
||||
void tst_Moc::cxx11Enums()
|
||||
@ -2272,21 +2273,26 @@ void tst_Moc::cxx11Enums()
|
||||
QFETCH(const QMetaObject *,meta);
|
||||
QCOMPARE(meta->enumeratorOffset(), 0);
|
||||
|
||||
QFETCH(QByteArray, typeName);
|
||||
QFETCH(QByteArray, enumName);
|
||||
QFETCH(char, prefix);
|
||||
QFETCH(bool, isScoped);
|
||||
|
||||
int idx;
|
||||
idx = meta->indexOfEnumerator(enumName);
|
||||
int idx = meta->indexOfEnumerator(typeName);
|
||||
QVERIFY(idx != -1);
|
||||
QCOMPARE(meta->indexOfEnumerator(enumName), idx);
|
||||
|
||||
QCOMPARE(meta->enumerator(idx).enclosingMetaObject(), meta);
|
||||
QCOMPARE(meta->enumerator(idx).isValid(), true);
|
||||
QCOMPARE(meta->enumerator(idx).keyCount(), 4);
|
||||
QCOMPARE(meta->enumerator(idx).name(), enumName.constData());
|
||||
QCOMPARE(meta->enumerator(idx).name(), typeName.constData());
|
||||
QCOMPARE(meta->enumerator(idx).enumName(), enumName.constData());
|
||||
bool isFlag = meta->enumerator(idx).isFlag();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
QByteArray v = prefix + QByteArray::number(i);
|
||||
QCOMPARE(meta->enumerator(idx).keyToValue(v), i);
|
||||
QCOMPARE(meta->enumerator(idx).valueToKey(i), v.constData());
|
||||
const int value = isFlag ? (1 << i) : i;
|
||||
QCOMPARE(meta->enumerator(idx).keyToValue(v), value);
|
||||
QCOMPARE(meta->enumerator(idx).valueToKey(value), v.constData());
|
||||
}
|
||||
QCOMPARE(meta->enumerator(idx).isScoped(), isScoped);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user