From 44cc1e256e2ad01e728f15996d727928e040fbd8 Mon Sep 17 00:00:00 2001 From: nerix Date: Sat, 24 Jun 2023 22:03:54 +0200 Subject: [PATCH] Fix partially broken filters on Qt 6 (#4702) --- CHANGELOG.md | 1 + .../lang/expressions/BinaryOperation.cpp | 53 ++++++++++++++++--- .../lang/expressions/ListExpression.cpp | 2 +- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf8e80af..87c3da492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Bugfix: Fixed a crash when opening and closing a reply thread and switching the user. (#4675) - Bugfix: Fix visual glitches with smooth scrolling. (#4501) - Bugfix: Fixed pings firing for the "Your username" highlight when not signed in. (#4698) +- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702) - Dev: Added command to set Qt's logging filter/rules at runtime (`/c2-set-logging-rules`). (#4637) - Dev: Added the ability to see & load custom themes from the Themes directory. No stable promises are made of this feature, changes might be made that breaks custom themes without notice. (#4570) - Dev: Added test cases for emote and tab completion. (#4644) diff --git a/src/controllers/filters/lang/expressions/BinaryOperation.cpp b/src/controllers/filters/lang/expressions/BinaryOperation.cpp index d3dbac4fe..d057ac783 100644 --- a/src/controllers/filters/lang/expressions/BinaryOperation.cpp +++ b/src/controllers/filters/lang/expressions/BinaryOperation.cpp @@ -2,6 +2,43 @@ #include +namespace { + +/// Loosely compares `lhs` with `rhs`. +/// This attempts to convert both variants to a common type if they're not equal. +bool looselyCompareVariants(QVariant &lhs, QVariant &rhs) +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + // Qt 6 and later don't convert types as much as Qt 5 did when comparing. + // + // Based on QVariant::cmp from Qt 5.15 + // https://github.com/qt/qtbase/blob/29400a683f96867133b28299c0d0bd6bcf40df35/src/corelib/kernel/qvariant.cpp#L4039-L4071 + if (lhs.metaType() != rhs.metaType()) + { + if (rhs.canConvert(lhs.metaType())) + { + if (!rhs.convert(lhs.metaType())) + { + return false; + } + } + else + { + // try the opposite conversion, it might work + qSwap(lhs, rhs); + if (!rhs.convert(lhs.metaType())) + { + return false; + } + } + } +#endif + + return lhs == rhs; +} + +} // namespace + namespace chatterino::filters { BinaryOperation::BinaryOperation(TokenType op, ExpressionPtr left, @@ -60,14 +97,14 @@ QVariant BinaryOperation::execute(const ContextMap &context) const return left.toString().compare(right.toString(), Qt::CaseInsensitive) == 0; } - return left == right; + return looselyCompareVariants(left, right); case NEQ: if (variantTypesMatch(left, right, QMetaType::QString)) { return left.toString().compare(right.toString(), Qt::CaseInsensitive) != 0; } - return left != right; + return !looselyCompareVariants(left, right); case LT: if (convertVariantTypes(left, right, QMetaType::Int)) return left.toInt() < right.toInt(); @@ -92,13 +129,13 @@ QVariant BinaryOperation::execute(const ContextMap &context) const Qt::CaseInsensitive); } - if (variantIs(left.type(), QMetaType::QVariantMap) && + if (variantIs(left, QMetaType::QVariantMap) && right.canConvert(QMetaType::QString)) { return left.toMap().contains(right.toString()); } - if (variantIs(left.type(), QMetaType::QVariantList)) + if (variantIs(left, QMetaType::QVariantList)) { return left.toList().contains(right); } @@ -112,7 +149,7 @@ QVariant BinaryOperation::execute(const ContextMap &context) const return false; case STARTS_WITH: - if (variantIs(left.type(), QMetaType::QStringList) && + if (variantIs(left, QMetaType::QStringList) && right.canConvert(QMetaType::QString)) { auto list = left.toStringList(); @@ -121,7 +158,7 @@ QVariant BinaryOperation::execute(const ContextMap &context) const Qt::CaseInsensitive) == 0; } - if (variantIs(left.type(), QMetaType::QVariantList)) + if (variantIs(left, QMetaType::QVariantList)) { return left.toList().startsWith(right); } @@ -136,7 +173,7 @@ QVariant BinaryOperation::execute(const ContextMap &context) const return false; case ENDS_WITH: - if (variantIs(left.type(), QMetaType::QStringList) && + if (variantIs(left, QMetaType::QStringList) && right.canConvert(QMetaType::QString)) { auto list = left.toStringList(); @@ -145,7 +182,7 @@ QVariant BinaryOperation::execute(const ContextMap &context) const Qt::CaseInsensitive) == 0; } - if (variantIs(left.type(), QMetaType::QVariantList)) + if (variantIs(left, QMetaType::QVariantList)) { return left.toList().endsWith(right); } diff --git a/src/controllers/filters/lang/expressions/ListExpression.cpp b/src/controllers/filters/lang/expressions/ListExpression.cpp index cd57a64ec..c0bf5ef8b 100644 --- a/src/controllers/filters/lang/expressions/ListExpression.cpp +++ b/src/controllers/filters/lang/expressions/ListExpression.cpp @@ -12,7 +12,7 @@ QVariant ListExpression::execute(const ContextMap &context) const for (const auto &exp : this->list_) { auto res = exp->execute(context); - if (allStrings && variantIsNot(res.type(), QMetaType::QString)) + if (allStrings && variantIsNot(res, QMetaType::QString)) { allStrings = false; }