QMetaEnum: let key(s)ToValue match fully-qualified unscoped enumerators
For an unscoped enumerator, e.g.: namespace N { class C { enum E { F }; }; }; N::C::F and N::C::E::F are equivalent and key(s)ToValue should match both. This already works for scoped enums because the name of the enum can't be dropped. Fixes: QTBUG-118240 Pick-to: 6.6 Change-Id: I84d7bbb7aa8f82b2a7c2bc7e4edd5d77d37335c4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
3936d254ca
commit
9e6c9eda6f
@ -3193,6 +3193,33 @@ const char *QMetaEnum::scope() const
|
||||
return mobj ? mobj->className() : nullptr;
|
||||
}
|
||||
|
||||
static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
|
||||
{
|
||||
const QByteArrayView className = e->enclosingMetaObject()->className();
|
||||
|
||||
// Typical use-cases:
|
||||
// a) Unscoped: namespace N { class C { enum E { F }; }; }; key == "N::C::F"
|
||||
// b) Scoped: namespace N { class C { enum class E { F }; }; }; key == "N::C::E::F"
|
||||
if (scope == className)
|
||||
return true;
|
||||
|
||||
// Not using name() because if isFlag() is true, we want the actual name
|
||||
// of the enum, e.g. "MyFlag", not "MyFlags", e.g.
|
||||
// enum MyFlag { F1, F2 }; Q_DECLARE_FLAGS(MyFlags, MyFlag);
|
||||
QByteArrayView name = e->enumName();
|
||||
|
||||
// Match fully qualified enumerator in unscoped enums, key == "N::C::E::F"
|
||||
// equivalent to use-case "a" above
|
||||
const auto sz = className.size();
|
||||
if (scope.size() == sz + qsizetype(qstrlen("::")) + name.size()
|
||||
&& scope.startsWith(className)
|
||||
&& scope.sliced(sz, 2) == "::"
|
||||
&& scope.sliced(sz + 2) == name)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the integer value of the given enumeration \a key, or -1
|
||||
if \a key is not defined.
|
||||
@ -3210,9 +3237,10 @@ int QMetaEnum::keyToValue(const char *key, bool *ok) const
|
||||
*ok = false;
|
||||
if (!mobj || !key)
|
||||
return -1;
|
||||
|
||||
const auto [scope, enumKey] = parse_scope(QLatin1StringView(key));
|
||||
for (int i = 0; i < int(data.keyCount()); ++i) {
|
||||
if ((!scope || *scope == objectClassName(mobj))
|
||||
if ((!scope || isScopeMatch(*scope, this))
|
||||
&& enumKey == stringDataView(mobj, mobj->d.data[data.data() + 2 * i])) {
|
||||
if (ok != nullptr)
|
||||
*ok = true;
|
||||
@ -3317,7 +3345,7 @@ int QMetaEnum::keysToValue(const char *keys, bool *ok) const
|
||||
return -1;
|
||||
for (const auto &untrimmed : list) {
|
||||
const auto parsed = parse_scope(untrimmed.trimmed());
|
||||
if (parsed.scope && *parsed.scope != objectClassName(mobj))
|
||||
if (parsed.scope && !isScopeMatch(*parsed.scope, this))
|
||||
return -1; // wrong type name in qualified name
|
||||
if (auto thisValue = lookup(parsed.key))
|
||||
value |= *thisValue;
|
||||
|
@ -2366,6 +2366,8 @@ void tst_QMetaObject::keysToValue()
|
||||
QVERIFY(!me.isFlag());
|
||||
QCOMPARE(QByteArray(me.scope()), QByteArray("MyNamespace::" + name));
|
||||
QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum2", &ok), 1);
|
||||
// Fully qualified unscoped enumerator
|
||||
QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum::MyEnum2", &ok), 1);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(me.keyToValue(name + "::MyEnum2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
@ -2395,6 +2397,9 @@ void tst_QMetaObject::keysToValue()
|
||||
QCOMPARE(QByteArray(mf.scope()), QByteArray("MyNamespace::" + name));
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
// Fully qualified
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue(name + "::MyFlag2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::MyFlag2", &ok), -1);
|
||||
@ -2404,7 +2409,12 @@ void tst_QMetaObject::keysToValue()
|
||||
QCOMPARE(mf.keysToValue("MyFlag", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
QCOMPARE(QLatin1String(mf.valueToKey(2)), QLatin1String("MyFlag2"));
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3);
|
||||
|
||||
const QByteArray prefix = "MyNamespace::" + name;
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag1|" + prefix + "::MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
// Fully qualified
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag::MyFlag1|" + prefix + "::MyFlag::MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue(name + "::MyFlag1|" + name + "::MyFlag2", &ok), -1);
|
||||
QCOMPARE(ok, false);
|
||||
@ -2416,7 +2426,10 @@ void tst_QMetaObject::keysToValue()
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2|MyNamespace::" + name + "::MyFlag2", &ok), 2);
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag2|" + prefix + "::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
// Fully qualified
|
||||
QCOMPARE(mf.keysToValue(prefix + "::MyFlag::MyFlag2|" + prefix + "::MyFlag::MyFlag2", &ok), 2);
|
||||
QCOMPARE(ok, true);
|
||||
QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2"));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user