/* This file is part of the KTextTemplate library SPDX-FileCopyrightText: 2010 Michael Jansen SPDX-FileCopyrightText: 2010 Stephen Kelly SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef KTEXTTEMPLATE_METATYPE_H #define KTEXTTEMPLATE_METATYPE_H #include "ktexttemplate_export.h" #include "typeaccessor.h" #include namespace KTextTemplate { /*! \class KTextTemplate::MetaType \inheaderfile KTextTemplate/MetaType \inmodule KTextTemplate \brief The MetaType is the interface to the KTextTemplate introspection system. The MetaType class is used as part of the type registration system of KTextTemplate. */ class KTEXTTEMPLATE_EXPORT MetaType { public: /*! \internal The signature for a property lookup method */ typedef QVariant (*LookupFunction)(const QVariant &, const QString &); /*! \internal Registers a property lookup method */ static void registerLookUpOperator(int id, LookupFunction f); /*! \internal */ static void internalLock(); /*! \internal */ static void internalUnlock(); /*! \internal */ static QVariant lookup(const QVariant &object, const QString &property); /*! \internal */ static bool lookupAlreadyRegistered(int id); private: MetaType(); }; namespace { /* This is a helper to select an appropriate overload of indexAccess */ template struct LookupTrait { static QVariant doLookUp(const QVariant &object, const QString &property) { typedef typename KTextTemplate::TypeAccessor Accessor; return Accessor::lookUp(object.value(), property); } }; template struct LookupTrait { static QVariant doLookUp(const QVariant &object, const QString &property) { typedef typename KTextTemplate::TypeAccessor Accessor; return Accessor::lookUp(object.value(), property); } }; template static int doRegister(int id) { if (MetaType::lookupAlreadyRegistered(id)) return id; QVariant (*lf)(const QVariant &, const QString &) = LookupTrait::doLookUp; MetaType::registerLookUpOperator(id, reinterpret_cast(lf)); return id; } /* Register a type so KTextTemplate knows how to handle it. */ template struct InternalRegisterType { static int doReg() { const int id = qMetaTypeId(); return doRegister(id); } }; template struct InternalRegisterType { static int doReg() { const int id = qMetaTypeId(); return doRegister(id); } }; } /*! \relates KTextTemplate::MetaType Registers the type RealType with the metatype system. This method can take a second template parameter to specify a cast that should be invoked during registration. This is useful if a base type is already supported. \code class SomeType { public: QString someProp() const; }; // define some introspectable API for SomeType KTEXTTEMPLATE_BEGIN_LOOKUP(SomeType) if (property == "someProp") return object.someProp(); KTEXTTEMPLATE_END_LOOKUP class OtherType : public SomeType { // ... }; registerMetaType(); // Only the introspectable API from SomeType is needed, so we can reuse that registration. registerMetaType(); \endcode */ template int registerMetaType() { MetaType::internalLock(); const int id = InternalRegisterType::doReg(); MetaType::internalUnlock(); return id; } /*! \internal Register a type so %KTextTemplate knows how to handle it. This is a convenience method. */ template int registerMetaType() { return registerMetaType(); } } // namespace KTextTemplate /*! Top boundary of a lookup function for Type. \macro KTEXTTEMPLATE_BEGIN_LOOKUP(Type) \relates KTextTemplate::MetaType */ #define KTEXTTEMPLATE_BEGIN_LOOKUP(Type) \ namespace KTextTemplate \ { \ template<> \ inline QVariant TypeAccessor::lookUp(const Type &object, const QString &property) \ { /*! Top boundary of a lookup function for Type*. \macro KTEXTTEMPLATE_BEGIN_LOOKUP_PTR(Type) \relates KTextTemplate::MetaType */ #define KTEXTTEMPLATE_BEGIN_LOOKUP_PTR(Type) \ namespace KTextTemplate \ { \ template<> \ inline QVariant TypeAccessor::lookUp(const Type *const object, const QString &property) \ { /*! Bottom boundary of a lookup function for Type. \macro KTEXTTEMPLATE_END_LOOKUP \relates KTextTemplate::MetaType */ #define KTEXTTEMPLATE_END_LOOKUP \ return QVariant(); \ } \ } #endif // #define KTEXTTEMPLATE_METATYPE_H