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