summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorAhmad Samir <a.samirh78@gmail.com>2023-10-27 17:25:25 +0200
committerAhmad Samir <a.samirh78@gmail.com>2023-11-26 22:51:49 +0200
commit9e6c9eda6f7f98b5308703edea47d204f54ffdf2 (patch)
tree7fc03fb369828bba6d783b9301d223c4b0812a28 /src/corelib/kernel
parent3936d254ca0e7259cd97238c31df8413d03fd475 (diff)
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>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qmetaobject.cpp32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 0873e8811d..f82d793f24 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -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;