diff options
author | Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com> | 2013-03-20 17:14:38 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-05-27 19:58:19 +0200 |
commit | 7ed15da3c1b9e2bb26f414a10bfc6e6d79d7cc7b (patch) | |
tree | c315f3b0e09bb745822d2b310559e8c3b2672cc9 /src/corelib/kernel/qmetatype.cpp | |
parent | 63354e0d097116138e7d998a01194f5ee502117a (diff) |
Core: QDebug and comparison operator support metatypes.
This patch adds a way to enable operator<, operator== and operator<<
into QDebug for QVariants with custom types.
Change-Id: I3d12d891bd7252ad2b8f1de69bced354800a1f29
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
Diffstat (limited to 'src/corelib/kernel/qmetatype.cpp')
-rw-r--r-- | src/corelib/kernel/qmetatype.cpp | 140 |
1 files changed, 124 insertions, 16 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index bfc48774b5..112ef747a3 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -420,38 +420,34 @@ public: int alias; }; -class QMetaTypeConversionRegistry +template<typename T, typename Key> +class QMetaTypeFunctionRegistry { public: - typedef QPair<int, int> Key; - - ~QMetaTypeConversionRegistry() + ~QMetaTypeFunctionRegistry() { const QWriteLocker locker(&lock); map.clear(); } - bool contains(int from, int to) const + bool contains(Key k) const { - const Key k(from, to); const QReadLocker locker(&lock); return map.contains(k); } - bool insertIfNotContains(int from, int to, const QtPrivate::AbstractConverterFunction *f) + bool insertIfNotContains(Key k, const T *f) { - const Key k(from, to); const QWriteLocker locker(&lock); - const QtPrivate::AbstractConverterFunction* &fun = map[k]; + const T* &fun = map[k]; if (fun != 0) return false; fun = f; return true; } - const QtPrivate::AbstractConverterFunction *function(int from, int to) const + const T *function(Key k) const { - const Key k(from, to); const QReadLocker locker(&lock); return map.value(k, 0); } @@ -464,9 +460,16 @@ public: } private: mutable QReadWriteLock lock; - QHash<Key, const QtPrivate::AbstractConverterFunction *> map; + QHash<Key, const T *> map; }; +typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractConverterFunction,QPair<int,int> > +QMetaTypeConverterRegistry; +typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractComparatorFunction,int> +QMetaTypeComparatorRegistry; +typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int> +QMetaTypeDebugStreamRegistry; + namespace { union CheckThatItIsPod @@ -478,7 +481,9 @@ union CheckThatItIsPod Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE); Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes) Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock) -Q_GLOBAL_STATIC(QMetaTypeConversionRegistry, customTypesConversionRegistry) +Q_GLOBAL_STATIC(QMetaTypeConverterRegistry, customTypesConversionRegistry) +Q_GLOBAL_STATIC(QMetaTypeComparatorRegistry, customTypesComparatorRegistry) +Q_GLOBAL_STATIC(QMetaTypeDebugStreamRegistry, customTypesDebugStreamRegistry) /*! \fn bool QMetaType::registerConverter() @@ -512,6 +517,23 @@ Q_GLOBAL_STATIC(QMetaTypeConversionRegistry, customTypesConversionRegistry) */ /*! + \fn bool QMetaType::registerComparators() + \since 5.2 + Registers comparison operetarors for the user-registered type T. This requires T to have + both an operator== and an operator<. + Returns true if the registration succeeded, otherwise false. +*/ + +#ifndef QT_NO_DEBUG_STREAM +/*! + \fn bool QMetaType::registerDebugStreamOperator() + Registers the debug stream operator for the user-registered type T. This requires T to have + an operator<<(QDebug dbg, T). + Returns true if the registration succeeded, otherwise false. +*/ +#endif + +/*! Registers function \a f as converter function from type id \a from to \a to. If there's already a conversion registered, this does nothing but deleting \a f. Returns true if the registration succeeded, otherwise false. @@ -520,7 +542,7 @@ Q_GLOBAL_STATIC(QMetaTypeConversionRegistry, customTypesConversionRegistry) */ bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunction *f, int from, int to) { - if (!customTypesConversionRegistry()->insertIfNotContains(from, to, f)) { + if (!customTypesConversionRegistry()->insertIfNotContains(qMakePair(from, to), f)) { qWarning("Type conversion already registered from type %s to type %s", QMetaType::typeName(from), QMetaType::typeName(to)); return false; @@ -538,6 +560,58 @@ void QMetaType::unregisterConverterFunction(int from, int to) customTypesConversionRegistry()->remove(from, to); } +bool QMetaType::registerComparatorFunction(const QtPrivate::AbstractComparatorFunction *f, int type) +{ + if (!customTypesComparatorRegistry()->insertIfNotContains(type, f)) { + qWarning("Comparators already registered for type %s", QMetaType::typeName(type)); + return false; + } + return true; +} + +/*! + \fn bool QMetaType::hasRegisteredComparators() + Returns true, if the meta type system has registered comparators for type T. + \since 5.2 + */ + +/*! + Returns true, if the meta type system has registered comparators for type id \a typeId. + \since 5.2 + */ +bool QMetaType::hasRegisteredComparators(int typeId) +{ + return customTypesComparatorRegistry()->contains(typeId); +} + +#ifndef QT_NO_DEBUG_STREAM +bool QMetaType::registerDebugStreamOperatorFunction(const QtPrivate::AbstractDebugStreamFunction *f, + int type) +{ + if (!customTypesDebugStreamRegistry()->insertIfNotContains(type, f)) { + qWarning("Debug stream operator already registered for type %s", QMetaType::typeName(type)); + return false; + } + return true; +} + +/*! + \fn bool QMetaType::hasRegisteredDebugStreamOperator() + Returns true, if the meta type system has a registered debug stream operator for type T. + \since 5.2 + */ + +/*! + Returns true, if the meta type system has a registered debug stream operator for type + id \a typeId. + \since 5.2 +*/ +bool QMetaType::hasRegisteredDebugStreamOperator(int typeId) +{ + return customTypesDebugStreamRegistry()->contains(typeId); +} +#endif + /*! Converts the object at \a from from \a fromTypeId to the preallocated space at \a to typed \a toTypeId. Returns true, if the conversion succeeded, otherwise false. @@ -545,11 +619,45 @@ void QMetaType::unregisterConverterFunction(int from, int to) */ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId) { - const QtPrivate::AbstractConverterFunction * const f = customTypesConversionRegistry()->function(fromTypeId, toTypeId); + const QtPrivate::AbstractConverterFunction * const f = + customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId)); return f && f->convert(f, from, to); } /*! + Compares the objects at \a lhs and \a rhs. Both objects need to be of type \a typeId. + \a result is set to less than, equal to or greater than zero, if \a lhs is less than, equal to + or greater than \a rhs. Returns true, if the comparison succeeded, otherwiess false. + \since 5.2 +*/ +bool QMetaType::compare(const void *lhs, const void *rhs, int typeId, int* result) +{ + const QtPrivate::AbstractComparatorFunction * const f = + customTypesComparatorRegistry()->function(typeId); + if (!f) + return false; + if (f->equals(f, lhs, rhs)) + *result = 0; + else + *result = f->lessThan(f, lhs, rhs) ? -1 : 1; + return true; +} + +/*! + Streams the object at \a rhs of type \a typeId to the debug stream \a dbg. Returns true + on success, otherwise false. + \since 5.2 +*/ +bool QMetaType::debugStream(QDebug& dbg, const void *rhs, int typeId) +{ + const QtPrivate::AbstractDebugStreamFunction * const f = customTypesDebugStreamRegistry()->function(typeId); + if (!f) + return false; + f->stream(f, dbg, rhs); + return true; +} + +/*! \fn bool QMetaType::hasRegisteredConverterFunction() Returns true, if the meta type system has a registered conversion from type From to type To. \since 5.2 @@ -563,7 +671,7 @@ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId */ bool QMetaType::hasRegisteredConverterFunction(int fromTypeId, int toTypeId) { - return customTypesConversionRegistry()->contains(fromTypeId, toTypeId); + return customTypesConversionRegistry()->contains(qMakePair(fromTypeId, toTypeId)); } #ifndef QT_NO_DATASTREAM |