Advertisement
Guest User

CustomVariantComparator - Qt 4

a guest
Apr 5th, 2016
537
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.15 KB | None | 0 0
  1. // Copyright (C) 2015 Mathias Kunter
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Lesser General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7.  
  8. #pragma once
  9.  
  10. #include <QApplication>
  11. #include <QtGlobal>
  12. #include <QVariant>
  13.  
  14.  
  15. /**
  16.  * This class provides functionality to use QVariant::operator== and QVariant::operator!= for custom types in Qt 4
  17.  * (in Qt 5, use QMetaType::registerComparators() instead of this class, which is available since Qt 5.2).
  18.  *
  19.  * To enable the custom type comparison, all you have to do is to call CustomVariantComparator::setEnabled(true)
  20.  * after the QApplication or QCoreApplication instance has been created, and to put the Q_DEFINE_COMPARATOR macro
  21.  * next to the implementation of your custom type (thus, not in a header file!). So your code should look like this:
  22.  *
  23.  *
  24.  * @code
  25.  * ----- Foo.h -----
  26.  * class Foo {
  27.  * public:
  28.  *     bool operator==(const Foo &other) { return ...; }
  29.  * };
  30.  * Q_DECLARE_METATYPE(Foo)
  31.  * @endcode
  32.  *
  33.  *
  34.  * @code
  35.  * ----- Foo.cpp -----
  36.  * Q_DEFINE_COMPARATOR(Foo)
  37.  *
  38.  * // other Foo implementations go here
  39.  * @endcode
  40.  *
  41.  *
  42.  * The following code snippet will now invoke the Foo::operator==() function (but remember to call
  43.  * CustomVariantComparator::setEnabled(true) before):
  44.  *
  45.  * @code
  46.  * ----- main.cpp -----
  47.  * QVariant::fromValue(Foo()) == QVariant::fromValue(Foo())
  48.  * @endcode
  49.  */
  50. class CustomVariantComparator : private QVariant {
  51.    
  52. private:
  53.    
  54.     template <typename T> friend class CustomComparatorRegistrar;
  55.    
  56.     /**
  57.      * Returns the QVariant::Handler object which is used by QVariant by default.
  58.      */
  59.     static Handler &defaultHandler() {
  60.         static Handler defaultHandler = *handler;
  61.         return defaultHandler;
  62.     }
  63.    
  64.     /**
  65.      * Returns our custom QVariant::Handler object which is used to invoke our own customCompare() function.
  66.      */
  67.     static Handler &customHandler() {
  68.         static Handler customHandler = defaultHandler();
  69.         customHandler.compare = customCompare;
  70.         return customHandler;
  71.     }
  72.    
  73.     /**
  74.      * Returns all registered custom compare functions as a hash from the metatype ID to a custom compare function.
  75.      */
  76.     static QHash<int, f_compare> &customCompareFunctions() {
  77.         static QHash<int, f_compare> customCompareFunctions;
  78.         return customCompareFunctions;
  79.     }
  80.    
  81.     /**
  82.      * Registers the given metatype @a typeId with the given @a customCompareFunction.
  83.      */
  84.     static void registerCustomCompareFunction(int typeId, f_compare customCompareFunction) {
  85.         customCompareFunctions().insert(typeId, customCompareFunction);
  86.     }
  87.    
  88.     /**
  89.      * This is our custom compare function, which is invoked via our custom handler object. It compares the two
  90.      * given QVariant::Private objects @a a and @a b. If they contain a custom type, and if we also have a custom
  91.      * comparator function registered for this type, then we'll call it. For all other types, we'll just call the
  92.      * default QVariant compare function.
  93.      */
  94.     static bool customCompare(const Private *a, const Private *b) {
  95.         // Note that for all custom types, a->type will be equal to b->type here. This is because Qt otherwise
  96.         // wouldn't call this function. So it doesn't actually matter whether we check a->type or b->type here.
  97.         if (customCompareFunctions().contains(a->type)) {
  98.             // We have a custom comparator function installed for this data type, so call it.
  99.             return customCompareFunctions()[a->type](a, b);
  100.         } else {
  101.             // Use the default QVariant handler to perform the comparison.
  102.             return defaultHandler().compare(a, b);
  103.         }
  104.     }
  105.    
  106. public:
  107.    
  108.     /**
  109.      * Enables or disables custom variant comparisons, depending on the given @a enable argument. Note that this
  110.      * function must not be called before the QApplication or QCoreApplication instance has been created.
  111.      */
  112.     static void setEnabled(bool enable) {
  113.         Q_ASSERT_X(qApp != 0, "VariantComparator",
  114.             "setEnabled() must not be called before the QApplication or QCoreApplication instance has been created.");
  115.         handler = enable ? &customHandler() : &defaultHandler();
  116.     }
  117. };
  118.  
  119.  
  120. /**
  121.  * This is an internal helper class for registering custom comparator functions. Don't use it within your code.
  122.  */
  123. template <typename T> class CustomComparatorRegistrar { };
  124.  
  125. /**
  126.  * Defines the custom comparator function for the given @a Type. See the CustomVariantComparator class documentation
  127.  * for how to use it.
  128.  */
  129. #define Q_DEFINE_COMPARATOR(Type) \
  130.     template <> class CustomComparatorRegistrar<Type> { \
  131.         \
  132.     private: \
  133.         \
  134.         static CustomComparatorRegistrar<Type> instance; \
  135.         \
  136.         static Type value(const QVariant::Private *p) { \
  137.             return *reinterpret_cast<const Type *>(p->is_shared ? p->data.shared->ptr : &p->data.ptr); \
  138.         } \
  139.         \
  140.         static bool customCompare(const QVariant::Private *a, const QVariant::Private *b) { \
  141.             return value(a) == value(b); \
  142.         } \
  143.         \
  144.         CustomComparatorRegistrar<Type>() { \
  145.             CustomVariantComparator::registerCustomCompareFunction(qMetaTypeId<Type>(), customCompare); \
  146.         } \
  147.     }; \
  148.     \
  149.     CustomComparatorRegistrar<Type> CustomComparatorRegistrar<Type>::instance;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement