Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Copyright (C) 2015 Mathias Kunter
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Lesser General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- #pragma once
- #include <QApplication>
- #include <QtGlobal>
- #include <QVariant>
- /**
- * This class provides functionality to use QVariant::operator== and QVariant::operator!= for custom types in Qt 4
- * (in Qt 5, use QMetaType::registerComparators() instead of this class, which is available since Qt 5.2).
- *
- * To enable the custom type comparison, all you have to do is to call CustomVariantComparator::setEnabled(true)
- * after the QApplication or QCoreApplication instance has been created, and to put the Q_DEFINE_COMPARATOR macro
- * next to the implementation of your custom type (thus, not in a header file!). So your code should look like this:
- *
- *
- * @code
- * ----- Foo.h -----
- * class Foo {
- * public:
- * bool operator==(const Foo &other) { return ...; }
- * };
- * Q_DECLARE_METATYPE(Foo)
- * @endcode
- *
- *
- * @code
- * ----- Foo.cpp -----
- * Q_DEFINE_COMPARATOR(Foo)
- *
- * // other Foo implementations go here
- * @endcode
- *
- *
- * The following code snippet will now invoke the Foo::operator==() function (but remember to call
- * CustomVariantComparator::setEnabled(true) before):
- *
- * @code
- * ----- main.cpp -----
- * QVariant::fromValue(Foo()) == QVariant::fromValue(Foo())
- * @endcode
- */
- class CustomVariantComparator : private QVariant {
- private:
- template <typename T> friend class CustomComparatorRegistrar;
- /**
- * Returns the QVariant::Handler object which is used by QVariant by default.
- */
- static Handler &defaultHandler() {
- static Handler defaultHandler = *handler;
- return defaultHandler;
- }
- /**
- * Returns our custom QVariant::Handler object which is used to invoke our own customCompare() function.
- */
- static Handler &customHandler() {
- static Handler customHandler = defaultHandler();
- customHandler.compare = customCompare;
- return customHandler;
- }
- /**
- * Returns all registered custom compare functions as a hash from the metatype ID to a custom compare function.
- */
- static QHash<int, f_compare> &customCompareFunctions() {
- static QHash<int, f_compare> customCompareFunctions;
- return customCompareFunctions;
- }
- /**
- * Registers the given metatype @a typeId with the given @a customCompareFunction.
- */
- static void registerCustomCompareFunction(int typeId, f_compare customCompareFunction) {
- customCompareFunctions().insert(typeId, customCompareFunction);
- }
- /**
- * This is our custom compare function, which is invoked via our custom handler object. It compares the two
- * given QVariant::Private objects @a a and @a b. If they contain a custom type, and if we also have a custom
- * comparator function registered for this type, then we'll call it. For all other types, we'll just call the
- * default QVariant compare function.
- */
- static bool customCompare(const Private *a, const Private *b) {
- // Note that for all custom types, a->type will be equal to b->type here. This is because Qt otherwise
- // wouldn't call this function. So it doesn't actually matter whether we check a->type or b->type here.
- if (customCompareFunctions().contains(a->type)) {
- // We have a custom comparator function installed for this data type, so call it.
- return customCompareFunctions()[a->type](a, b);
- } else {
- // Use the default QVariant handler to perform the comparison.
- return defaultHandler().compare(a, b);
- }
- }
- public:
- /**
- * Enables or disables custom variant comparisons, depending on the given @a enable argument. Note that this
- * function must not be called before the QApplication or QCoreApplication instance has been created.
- */
- static void setEnabled(bool enable) {
- Q_ASSERT_X(qApp != 0, "VariantComparator",
- "setEnabled() must not be called before the QApplication or QCoreApplication instance has been created.");
- handler = enable ? &customHandler() : &defaultHandler();
- }
- };
- /**
- * This is an internal helper class for registering custom comparator functions. Don't use it within your code.
- */
- template <typename T> class CustomComparatorRegistrar { };
- /**
- * Defines the custom comparator function for the given @a Type. See the CustomVariantComparator class documentation
- * for how to use it.
- */
- #define Q_DEFINE_COMPARATOR(Type) \
- template <> class CustomComparatorRegistrar<Type> { \
- \
- private: \
- \
- static CustomComparatorRegistrar<Type> instance; \
- \
- static Type value(const QVariant::Private *p) { \
- return *reinterpret_cast<const Type *>(p->is_shared ? p->data.shared->ptr : &p->data.ptr); \
- } \
- \
- static bool customCompare(const QVariant::Private *a, const QVariant::Private *b) { \
- return value(a) == value(b); \
- } \
- \
- CustomComparatorRegistrar<Type>() { \
- CustomVariantComparator::registerCustomCompareFunction(qMetaTypeId<Type>(), customCompare); \
- } \
- }; \
- \
- CustomComparatorRegistrar<Type> CustomComparatorRegistrar<Type>::instance;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement