File indexing completed on 2025-02-09 04:28:38

0001 /*
0002   This file is part of the KTextTemplate library
0003 
0004   SPDX-FileCopyrightText: 2010 Michael Jansen <kde@michael-jansen.biz>
0005   SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
0006 
0007   SPDX-License-Identifier: LGPL-2.1-or-later
0008 
0009 */
0010 
0011 #ifndef KTEXTTEMPLATE_METATYPE_H
0012 #define KTEXTTEMPLATE_METATYPE_H
0013 
0014 #include "ktexttemplate_export.h"
0015 
0016 #include "typeaccessor.h"
0017 
0018 #include <QVariant>
0019 
0020 /// @file
0021 
0022 namespace KTextTemplate
0023 {
0024 
0025 /// @headerfile metatype.h <KTextTemplate/MetaType>
0026 
0027 #ifndef K_DOXYGEN
0028 /**
0029   @brief The **%MetaType** is the interface to the KTextTemplate introspection
0030   system.
0031 
0032   The **%MetaType** class is used as part of the type registration system of
0033   %KTextTemplate.
0034 
0035   @see @ref generic_types_and_templates
0036   @author Michael Jansen <kde@michael-jansen.biz>
0037   @author Stephen Kelly <steveire@gmail.com>
0038 */
0039 class KTEXTTEMPLATE_EXPORT MetaType
0040 {
0041 public:
0042     /**
0043       @internal The signature for a property lookup method
0044      */
0045     typedef QVariant (*LookupFunction)(const QVariant &, const QString &);
0046 
0047     /**
0048       @internal Registers a property lookup method
0049      */
0050     static void registerLookUpOperator(int id, LookupFunction f);
0051 
0052     /**
0053       @internal
0054      */
0055     static void internalLock();
0056 
0057     /**
0058       @internal
0059      */
0060     static void internalUnlock();
0061 
0062     /**
0063       @internal
0064      */
0065     static QVariant lookup(const QVariant &object, const QString &property);
0066 
0067     /**
0068       @internal
0069      */
0070     static bool lookupAlreadyRegistered(int id);
0071 
0072 private:
0073     MetaType();
0074 };
0075 #endif
0076 
0077 namespace
0078 {
0079 
0080 /*
0081   This is a helper to select an appropriate overload of indexAccess
0082  */
0083 template<typename RealType, typename HandleAs>
0084 struct LookupTrait {
0085     static QVariant doLookUp(const QVariant &object, const QString &property)
0086     {
0087         typedef typename KTextTemplate::TypeAccessor<RealType> Accessor;
0088         return Accessor::lookUp(object.value<RealType>(), property);
0089     }
0090 };
0091 
0092 template<typename RealType, typename HandleAs>
0093 struct LookupTrait<RealType &, HandleAs &> {
0094     static QVariant doLookUp(const QVariant &object, const QString &property)
0095     {
0096         typedef typename KTextTemplate::TypeAccessor<HandleAs &> Accessor;
0097         return Accessor::lookUp(object.value<HandleAs>(), property);
0098     }
0099 };
0100 
0101 template<typename RealType, typename HandleAs>
0102 static int doRegister(int id)
0103 {
0104     if (MetaType::lookupAlreadyRegistered(id))
0105         return id;
0106 
0107     QVariant (*lf)(const QVariant &, const QString &) = LookupTrait<RealType, HandleAs>::doLookUp;
0108 
0109     MetaType::registerLookUpOperator(id, reinterpret_cast<MetaType::LookupFunction>(lf));
0110 
0111     return id;
0112 }
0113 
0114 /*
0115   Register a type so KTextTemplate knows how to handle it.
0116  */
0117 template<typename RealType, typename HandleAs>
0118 struct InternalRegisterType {
0119     static int doReg()
0120     {
0121         const int id = qMetaTypeId<RealType>();
0122         return doRegister<RealType &, HandleAs &>(id);
0123     }
0124 };
0125 
0126 template<typename RealType, typename HandleAs>
0127 struct InternalRegisterType<RealType *, HandleAs *> {
0128     static int doReg()
0129     {
0130         const int id = qMetaTypeId<RealType *>();
0131         return doRegister<RealType *, HandleAs *>(id);
0132     }
0133 };
0134 }
0135 
0136 /**
0137   @brief Registers the type RealType with the metatype system.
0138 
0139   This method can take a second template parameter to specify a cast
0140   that should be invoked during registration. This is useful if a base type is
0141   already supported.
0142 
0143   @code
0144     class SomeType
0145     {
0146     public:
0147       QString someProp() const;
0148     };
0149 
0150     // define some introspectable API for SomeType
0151 
0152     KTEXTTEMPLATE_BEGIN_LOOKUP(SomeType)
0153       if (property == "someProp")
0154         return object.someProp();
0155     KTEXTTEMPLATE_END_LOOKUP
0156 
0157 
0158     class OtherType : public SomeType
0159     {
0160       // ...
0161     };
0162 
0163     registerMetaType<SomeType>();
0164 
0165     // Only the introspectable API from SomeType is needed, so we can reuse that
0166   registration.
0167     registerMetaType<OtherType, SomeType>();
0168   @endcode
0169 
0170   @see @ref generic_types_and_templates
0171  */
0172 template<typename RealType, typename HandleAs>
0173 int registerMetaType()
0174 {
0175     MetaType::internalLock();
0176 
0177     const int id = InternalRegisterType<RealType, HandleAs>::doReg();
0178 
0179     MetaType::internalUnlock();
0180 
0181     return id;
0182 }
0183 
0184 #ifndef K_DOXYGEN
0185 /**
0186   @internal
0187   Register a type so %KTextTemplate knows how to handle it.
0188 
0189   This is a convenience method.
0190  */
0191 template<typename Type>
0192 int registerMetaType()
0193 {
0194     return registerMetaType<Type, Type>();
0195 }
0196 
0197 #endif
0198 } // namespace KTextTemplate
0199 
0200 /**
0201   Top boundary of a lookup function for Type.
0202 
0203   @see @ref generic_types
0204  */
0205 #define KTEXTTEMPLATE_BEGIN_LOOKUP(Type)                                                                                                                       \
0206     namespace KTextTemplate                                                                                                                                    \
0207     {                                                                                                                                                          \
0208     template<>                                                                                                                                                 \
0209     inline QVariant TypeAccessor<Type &>::lookUp(const Type &object, const QString &property)                                                                  \
0210     {
0211 /**
0212   Top boundary of a lookup function for Type*.
0213 
0214   @see @ref generic_types
0215  */
0216 #define KTEXTTEMPLATE_BEGIN_LOOKUP_PTR(Type)                                                                                                                   \
0217     namespace KTextTemplate                                                                                                                                    \
0218     {                                                                                                                                                          \
0219     template<>                                                                                                                                                 \
0220     inline QVariant TypeAccessor<Type *>::lookUp(const Type *const object, const QString &property)                                                            \
0221     {
0222 /**
0223   Bottom boundary of a lookup function for Type.
0224 
0225   @see @ref generic_types
0226  */
0227 #define KTEXTTEMPLATE_END_LOOKUP                                                                                                                               \
0228     return QVariant();                                                                                                                                         \
0229     }                                                                                                                                                          \
0230     }
0231 
0232 #endif // #define KTEXTTEMPLATE_METATYPE_H