From 50c96c17b6c87d48418336dc124a6de3f1f1958b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 8 Jun 2020 12:55:43 +0200 Subject: Use the new support for comparisons in QMetaType for QVariant Remove the compare method in the QVariant::Handler struct. Rely on the generic support provided by QMetaType instead. [ChangeLog][Important Behavior Changes][QVariant] QVariant will now use builtin support in QMetaType to compare its content. This implies a behavioral change for some graphical types like QPixmap, QImage and QIcon that will never compare equal in Qt 6 (as they do not have a comparison operator). Change-Id: I30a6e7116c89124d11ed9052537cecc23f78116e Reviewed-by: Edward Welbourne --- src/corelib/kernel/qvariant.cpp | 51 ++++++---------------------------- src/corelib/kernel/qvariant.h | 10 +++---- src/corelib/kernel/qvariant_p.h | 43 ---------------------------- src/gui/kernel/qguivariant.cpp | 43 ---------------------------- src/widgets/kernel/qwidgetsvariant.cpp | 13 --------- 5 files changed, 13 insertions(+), 147 deletions(-) (limited to 'src') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f8859ddedc..63466f9de8 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -123,18 +123,6 @@ static bool isNull(const QVariant::Private *d) return QMetaTypeSwitcher::switcher(isNull, d->type().id()); } -/*! - \internal - - Compares \a a to \a b. The caller guarantees that \a a and \a b - are of the same type. - */ -static bool compare(const QVariant::Private *a, const QVariant::Private *b) -{ - QVariantComparator comparator(a, b); - return QMetaTypeSwitcher::switcher(comparator, a->type().id()); -} - /*! \internal */ @@ -1390,7 +1378,6 @@ static void streamDebug(QDebug dbg, const QVariant &v) const QVariant::Handler qt_kernel_variant_handler = { isNull, - compare, convert, #if !defined(QT_NO_DEBUG_STREAM) streamDebug @@ -1400,14 +1387,12 @@ const QVariant::Handler qt_kernel_variant_handler = { }; static bool dummyIsNull(const QVariant::Private *d) { Q_ASSERT_X(false, "QVariant::isNull", "Trying to call isNull on an unknown type"); return d->is_null; } -static bool dummyCompare(const QVariant::Private *, const QVariant::Private *) { Q_ASSERT_X(false, "QVariant", "Trying to compare an unknown types"); return false; } static bool dummyConvert(const QVariant::Private *, int, void *, bool *) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); return false; } #if !defined(QT_NO_DEBUG_STREAM) static void dummyStreamDebug(QDebug, const QVariant &) { Q_ASSERT_X(false, "QVariant", "Trying to convert an unknown type"); } #endif const QVariant::Handler qt_dummy_variant_handler = { dummyIsNull, - dummyCompare, dummyConvert, #if !defined(QT_NO_DEBUG_STREAM) dummyStreamDebug @@ -1468,17 +1453,6 @@ static bool customIsNull(const QVariant::Private *d) return false; } -static bool customCompare(const QVariant::Private *a, const QVariant::Private *b) -{ - const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data); - const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data); - - if (a->is_null && b->is_null) - return true; - - return !memcmp(a_ptr, b_ptr, a->type().sizeOf()); -} - static bool customConvert(const QVariant::Private *d, int t, void *result, bool *ok) { if (d->type().id() >= QMetaType::User || t >= QMetaType::User) { @@ -1506,7 +1480,6 @@ static void customStreamDebug(QDebug dbg, const QVariant &variant) { const QVariant::Handler qt_custom_variant_handler = { customIsNull, - customCompare, customConvert, #if !defined(QT_NO_DEBUG_STREAM) customStreamDebug @@ -3909,23 +3882,13 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private * /*! \internal */ -bool QVariant::cmp(const QVariant &v) const -{ - auto cmp_helper = [](const QVariant::Private &d1, const QVariant::Private &d2) { - Q_ASSERT(d1.type() == d2.type()); - auto metatype = d1.type(); - if (metatype.id() >= QMetaType::User) - return metatype.equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2))); - return handlerManager[d1.type().id()]->compare(&d1, &d2); - }; - +bool QVariant::equals(const QVariant &v) const +{ + auto metatype = d.type(); // try numerics first, with C++ type promotion rules (no conversion) - if (qIsNumericType(d.type().id()) && qIsNumericType(v.d.type().id())) + if (qIsNumericType(metatype.id()) && qIsNumericType(v.d.type().id())) return numericCompare(&d, &v.d) == 0; - if (d.type() == v.d.type()) - return cmp_helper(d, v.d); - QVariant v1 = *this; QVariant v2 = v; if (v2.canConvert(v1.d.type().id())) { @@ -3937,7 +3900,11 @@ bool QVariant::cmp(const QVariant &v) const if (!v2.convert(v1.d.type().id())) return false; } - return cmp_helper(v1.d, v2.d); + metatype = v1.metaType(); + // For historical reasons: QVariant() == QVariant() + if (!metatype.isValid()) + return true; + return metatype.equals(QT_PREPEND_NAMESPACE(constData(v1.d)), QT_PREPEND_NAMESPACE(constData(v2.d))); } /*! diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index e7b64c2aed..498ba57399 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -470,20 +470,18 @@ class Q_CORE_EXPORT QVariant }; public: typedef bool (*f_null)(const Private *); - typedef bool (*f_compare)(const Private *, const Private *); typedef bool (*f_convert)(const QVariant::Private *d, int t, void *, bool *); typedef void (*f_debugStream)(QDebug, const QVariant &); struct Handler { f_null isNull; - f_compare compare; f_convert convert; f_debugStream debugStream; }; inline bool operator==(const QVariant &v) const - { return cmp(v); } + { return equals(v); } inline bool operator!=(const QVariant &v) const - { return !cmp(v); } + { return !equals(v); } protected: friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &); @@ -501,7 +499,7 @@ public: #endif Private d; void create(int type, const void *copy); - bool cmp(const QVariant &other) const; + bool equals(const QVariant &other) const; bool convert(const int t, void *ptr) const; // ### Qt6: drop const private: @@ -584,7 +582,7 @@ private: inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2) { - return v1.cmp(*v2.v); + return v1.equals(*v2.v); } inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2) diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 8739cb5173..2cec8ff65b 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -212,49 +212,6 @@ public: } }; -template -class QVariantComparator { - template::IsAccepted> - struct FilteredComparator { - static bool compare(const QVariant::Private *a, const QVariant::Private *b) - { - return *v_cast(a) == *v_cast(b); - } - }; - template - struct FilteredComparator { - static bool compare(const QVariant::Private *, const QVariant::Private *) - { - // It is not possible to construct a QVariant containing not fully defined type - Q_ASSERT(false); - return false; - } - }; -public: - QVariantComparator(const QVariant::Private *a, const QVariant::Private *b) - : m_a(a), m_b(b) - { - Q_ASSERT(a->type() == b->type()); - } - - template - bool delegate(const T*) - { - return FilteredComparator::compare(m_a, m_b); - } - - bool delegate(const void*) { Q_ASSERT(false); return true; } - bool delegate(const QMetaTypeSwitcher::UnknownType*) - { - return true; // for historical reason invalid variant == invalid variant - } - bool delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return false; } -protected: - const QVariant::Private *m_a; - const QVariant::Private *m_b; -}; - - Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler(); template diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index 565e91d662..efd98f691d 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -121,48 +121,6 @@ static bool isNull(const QVariant::Private *d) return QMetaTypeSwitcher::switcher(isNull, d->type().id(), nullptr); } -// This class is a hack that customizes access to QPixmap, QBitmap, QCursor and QIcon -template -class QGuiVariantComparator : public QVariantComparator { - typedef QVariantComparator Base; -public: - QGuiVariantComparator(const QVariant::Private *a, const QVariant::Private *b) - : QVariantComparator(a, b) - {} - template - bool delegate(const T *p) - { - return Base::delegate(p); - } - bool delegate(const QPixmap*) - { - return v_cast(Base::m_a)->cacheKey() == v_cast(Base::m_b)->cacheKey(); - } - bool delegate(const QBitmap*) - { - return v_cast(Base::m_a)->cacheKey() == v_cast(Base::m_b)->cacheKey(); - } -#ifndef QT_NO_CURSOR - bool delegate(const QCursor*) - { - return v_cast(Base::m_a)->shape() == v_cast(Base::m_b)->shape(); - } -#endif -#ifndef QT_NO_ICON - bool delegate(const QIcon *) - { - return v_cast(Base::m_a)->cacheKey() == v_cast(Base::m_b)->cacheKey(); - } -#endif - bool delegate(const void *p) { return Base::delegate(p); } -}; - -static bool compare(const QVariant::Private *a, const QVariant::Private *b) -{ - QGuiVariantComparator comparator(a, b); - return QMetaTypeSwitcher::switcher(comparator, a->type().id(), nullptr); -} - static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) { @@ -306,7 +264,6 @@ static void streamDebug(QDebug dbg, const QVariant &v) const QVariant::Handler qt_gui_variant_handler = { isNull, - compare, convert, #if !defined(QT_NO_DEBUG_STREAM) streamDebug diff --git a/src/widgets/kernel/qwidgetsvariant.cpp b/src/widgets/kernel/qwidgetsvariant.cpp index 15a48bf683..31bb92bb2e 100644 --- a/src/widgets/kernel/qwidgetsvariant.cpp +++ b/src/widgets/kernel/qwidgetsvariant.cpp @@ -54,18 +54,6 @@ static bool isNull(const QVariant::Private *) return false; } -static bool compare(const QVariant::Private *a, const QVariant::Private *b) -{ - Q_ASSERT(a->type() == b->type()); - switch (a->type().id()) { - case QMetaType::QSizePolicy: - return *v_cast(a) == *v_cast(b); - default: - Q_ASSERT(false); - } - return false; -} - static bool convert(const QVariant::Private *d, int type, void *result, bool *ok) { Q_UNUSED(d); @@ -92,7 +80,6 @@ static void streamDebug(QDebug dbg, const QVariant &v) static const QVariant::Handler widgets_handler = { isNull, - compare, convert, #if !defined(QT_NO_DEBUG_STREAM) streamDebug -- cgit v1.2.3